בדיקת ביצועים

Android 8.0 כולל בדיקות ביצועים של Binder ו-hwbinder לגבי תפוקה זמן אחזור. למרות שיש הרבה תרחישים לזיהוי ביצועים שניתנים לזיהוי הרצת תרחישים כאלה יכולה להימשך זמן רב, ולעיתים קרובות לא זמין עד לאחר שילוב המערכת. באמצעות הביצועים שסופקו לביצוע בדיקות קל יותר במהלך הפיתוח, לאתר בעיות חמורות בשלב מוקדם יותר, ולשפר את חוויית המשתמש.

בדיקות הביצועים כוללות את ארבע הקטגוריות הבאות:

  • תפוקה של binder (זמין ב- system/libhwbinder/vts/performance/Benchmark_binder.cpp)
  • זמן האחזור של binder (זמין ב- frameworks/native/libs/binder/tests/schd-dbg.cpp)
  • תפוקת hwbinder (זמין ב- system/libhwbinder/vts/performance/Benchmark.cpp)
  • זמן אחזור hwbinder (זמין ב- system/libhwbinder/vts/performance/Latency.cpp)

מידע על binder ו-hwbinder

Binder ו-hwbinder הם מערכות של תקשורת בין תהליכים ב-Android (IPC) תשתיות שמשתפות מנהל התקן של Linux אבל כוללות את הרכיבים הבאים: הבדלים איכותיים:

יחס גובה-רוחב קלסר Hwbinder
המטרה צריך לספק סכמת IPC לשימוש כללי ל-framework תקשורת עם החומרה
נכס מותאמים לשימוש ב-Android framework זמן אחזור מינימלי בתקורה נמוכה
שינוי מדיניות התזמון של קדמת התמונה או הרקע כן לא
העברת ארגומנטים שימוש בסריאליזציה שנתמכת על ידי אובייקט Parcel שימוש במאגרי נתונים זמניים לצורך פיזור ומניעת התקורה לצורך העתקת נתונים שנדרשים הסדרת חבילות
ירושה של עדיפות לא כן

תהליכים של Binder ו-hwbinder

כלי הוויזואליזציה של המערכת מציג טרנזקציות באופן הבא:

איור 1. המחשה ויזואלית של מערכת סינון תוכן תהליכים.

בדוגמה שלמעלה:

  • ארבעת (4) התהליכים של schd-dbg הם תהליכי לקוח.
  • ארבעת (4) תהליכי החיבור הם תהליכי שרת (השם מתחיל ב- Binder ומסתיים במספר סידורי).
  • תהליך לקוח תמיד מותאם לתהליך שרת, שמיועד אל הלקוח שלו.
  • כל צמדי התהליכים של לקוח-שרת מתוזמנים באופן עצמאי על ידי ליבה (kernel) בו-זמנית.

ב-CPU 1, הליבה של מערכת ההפעלה מפעילה את הלקוח כדי לשלוח את הבקשה. לאחר מכן משתמשת באותו מעבד (CPU) ככל האפשר כדי להוציא תהליך ממצב שרת, וההקשר החוזר לאחר השלמת הבקשה.

תפוקה לעומת זמן אחזור

בעסקה מושלמת, שבה הלקוח והשרת עוברים עיבוד בצורה חלקה, בדיקות תפוקה וזמן אחזור לא מייצרות הבדלים משמעותיים הודעות. עם זאת, כש הליבה של מערכת ההפעלה מטפלת בבקשת הפרעה (IRQ) מחומרה, בהמתנה למנעולים או פשוט בחירה שלא לטפל בהודעה מיד יכולה להיווצר בועת זמן אחזור.

איור 2. בועת זמן אחזור בגלל הבדלים תפוקה וזמן אחזור.

בדיקת התפוקה יוצרת מספר גדול של עסקאות עם סוגים שונים של גדלים של מטענים ייעודיים (payloads), דבר שמספק הערכה טובה לגבי זמן העסקה הרגיל (ב והתפוקה המקסימלית שכלי הקשר יכול להשיג.

לעומת זאת, הבדיקה של זמן האחזור לא מבצעת פעולות במטען הייעודי (payload) כדי לצמצם במועד הרגיל של העסקה. אנחנו יכולים להשתמש בזמן העסקה כדי להעריך את הקישור ליצור נתונים סטטיסטיים עבור המקרה הגרוע ביותר, ולחשב את היחס עסקאות שזמן האחזור שלהן עומד בתאריך יעד שנקבע.

טיפול בהפוכות בעדיפות

היפוך עדיפות מתרחשת כאשר שרשור עם עדיפות גבוהה יותר נמצא באופן לוגי בהמתנה לשרשור עם עדיפות נמוכה יותר. לאפליקציות בזמן אמת (RT) יש בעיית היפוך עדיפות:

איור 3. היפוך העדיפות בזמן אמת תרגום מכונה.

כשמשתמשים בתזמון פגישות הוגן (CFS) של Linux, השרשור תמיד מתחיל ב-thread יכולים לפעול גם אם לשרשורים אחרים יש עדיפות גבוהה יותר. כתוצאה מכך, אפליקציות עם היפוך העדיפות של הטיפול בתזמון CFS, כמצופה ולא כבעיה. במקרים שבהם ל-framework של Android נדרש תזמון RT כדי להבטיח את ההרשאות של שרשורים בעדיפות גבוהה, עם זאת, היפוך עדיפות חייב להיפתר.

דוגמה להיפוך עדיפות במהלך טרנזקציית binder (שרשור RT הוא נחסמו מבחינה לוגית על ידי שרשורי CFS אחרים כשממתינים ל-thread binder ):

איור 4. היפוך עדיפות, חסימה בזמן אמת שרשורים.

כדי להימנע מחסימות, אתם יכולים להשתמש בירושה בעדיפות גבוהה להעברה זמנית לטיפול ברמה גבוהה יותר את ה-thread של Binder לשרשור RT כאשר הוא מספק שירות לבקשה מלקוח RT. חשוב לזכור שלתזמון RT יש משאבים מוגבלים וצריך להשתמש בו בזהירות. במערכת עם n מעבדים, זה המספר המקסימלי של RT ב-RT. שרשורים הוא גם n; יכול להיות ששרשורי RT נוספים יצטרכו להמתין (ולכן אם את כל המעבדים (CPU) לוקחים בשרשורי RT אחרים, מפספסים את המועדים האחרונים.

כדי לפתור את כל היפוך העדיפות, אפשר להשתמש בעדיפות גם ל-binder וגם ל-hwbinder. עם זאת, מכיוון שאנחנו משתמשים ב-Binder בכל המערכת, מתן עדיפות לירושה של טרנזקציות קלסרים לשלוח ספאם למערכת עם יותר שרשורי RT ממה שהיא יכולה לספק.

הפעלת בדיקות תפוקה

בדיקת התפוקה מתבצעת מול תפוקת העסקאות של binder/hwbinder. לחשבון במערכת שלא עמוסה מדי, בועות של זמן אחזור הן נדירות וההשפעה שלהן ניתנת לביטול כל עוד מספר החזרות גבוה מספיק.

  • בדיקת התפוקה של binder נמצאת במצב system/libhwbinder/vts/performance/Benchmark_binder.cpp.
  • בדיקת התפוקה של hwbinder system/libhwbinder/vts/performance/Benchmark.cpp.

תוצאות בדיקה

דוגמאות לתוצאות של בדיקת תפוקה עבור טרנזקציות באמצעות מטען ייעודי (payload) שונה גדלים:

Benchmark                      Time          CPU           Iterations
---------------------------------------------------------------------
BM_sendVec_binderize/4         70302 ns      32820 ns      21054
BM_sendVec_binderize/8         69974 ns      32700 ns      21296
BM_sendVec_binderize/16        70079 ns      32750 ns      21365
BM_sendVec_binderize/32        69907 ns      32686 ns      21310
BM_sendVec_binderize/64        70338 ns      32810 ns      21398
BM_sendVec_binderize/128       70012 ns      32768 ns      21377
BM_sendVec_binderize/256       69836 ns      32740 ns      21329
BM_sendVec_binderize/512       69986 ns      32830 ns      21296
BM_sendVec_binderize/1024      69714 ns      32757 ns      21319
BM_sendVec_binderize/2k        75002 ns      34520 ns      20305
BM_sendVec_binderize/4k        81955 ns      39116 ns      17895
BM_sendVec_binderize/8k        95316 ns      45710 ns      15350
BM_sendVec_binderize/16k      112751 ns      54417 ns      12679
BM_sendVec_binderize/32k      146642 ns      71339 ns       9901
BM_sendVec_binderize/64k      214796 ns     104665 ns       6495
  • זמן מציין את עיכוב הנסיעה הלוך ושוב שנמדד בזמן אמת.
  • הערך CPU מציין את הזמן המצטבר שבו מתזמנים מעבדים (CPU) לצורך הבדיקה.
  • הערך איטרציות מציין את מספר הפעמים שפונקציית הבדיקה בוצעה.

לדוגמה, למטען ייעודי (payload) בגודל 8 בייטים:

BM_sendVec_binderize/8         69974 ns      32700 ns      21296

... התפוקה המקסימלית שה-binder יכול להשיג מחושב כך:

תפוקה מקסימלית עם מטען ייעודי (payload) של 8 בייטים = (8 * 21296)/69974 ~= 2.423 b/ns ~= 2.268 Gb/s

אפשרויות בדיקה

כדי לקבל תוצאות בקובץ .json, צריך להריץ את הבדיקה עם ארגומנט --benchmark_format=json:

libhwbinder_benchmark --benchmark_format=json
{
  "context": {
    "date": "2017-05-17 08:32:47",
    "num_cpus": 4,
    "mhz_per_cpu": 19,
    "cpu_scaling_enabled": true,
    "library_build_type": "release"
  },
  "benchmarks": [
    {
      "name": "BM_sendVec_binderize/4",
      "iterations": 32342,
      "real_time": 47809,
      "cpu_time": 21906,
      "time_unit": "ns"
    },
   ….
}

הרצת בדיקות של זמן אחזור

בדיקת זמן האחזור מודדת את הזמן שחולף עד שהלקוח מתחיל אתחול הטרנזקציה, מעבר לתהליך השרת לצורך טיפול מקבלים את התוצאה. במסגרת הבדיקה מתבצע גם חיפוש של התנהגויות לא תקינות ידועות של המתזמנים יכולה להשפיע לרעה על זמן האחזור של העסקה, למשל כלי תזמון שלא תומכים בירושה בעדיפות או פועלים בהתאם לדגל הסנכרון.

  • בדיקת זמן האחזור של binder frameworks/native/libs/binder/tests/schd-dbg.cpp
  • בדיקת זמן האחזור של hwbinder system/libhwbinder/vts/performance/Latency.cpp

תוצאות בדיקה

תוצאות (בקובץ .json) מציגות נתונים סטטיסטיים לגבי זמן האחזור הממוצע/הטוב ביותר/הגרוע ביותר, וגם מספר המועדים האחרונים החסרים.

אפשרויות בדיקה

בדיקות זמן אחזור כוללות את האפשרויות הבאות:

הוראה תיאור
-i value ציון מספר החזרות.
-pair value מציינים את המספר של צמדי התהליכים.
-deadline_us 2500 מציינים את תאריך היעד אצלנו.
-v קבלת פלט מפורט (ניפוי באגים).
-trace מפסיקים את המעקב אחרי המועד האחרון.

הקטעים הבאים מתארים כל אפשרות, מתארים את השימוש ומספקים תוצאות לדוגמה.

ציון איטרציות

דוגמה שבה משביתים מספר גדול של איטרציות ופלט מפורט:

libhwbinder_latency -i 5000 -pair 3
{
"cfg":{"pair":3,"iterations":5000,"deadline_us":2500},
"P0":{"SYNC":"GOOD","S":9352,"I":10000,"R":0.9352,
  "other_ms":{ "avg":0.2 , "wst":2.8 , "bst":0.053, "miss":2, "meetR":0.9996},
  "fifo_ms": { "avg":0.16, "wst":1.5 , "bst":0.067, "miss":0, "meetR":1}
},
"P1":{"SYNC":"GOOD","S":9334,"I":10000,"R":0.9334,
  "other_ms":{ "avg":0.19, "wst":2.9 , "bst":0.055, "miss":2, "meetR":0.9996},
  "fifo_ms": { "avg":0.16, "wst":3.1 , "bst":0.066, "miss":1, "meetR":0.9998}
},
"P2":{"SYNC":"GOOD","S":9369,"I":10000,"R":0.9369,
  "other_ms":{ "avg":0.19, "wst":4.8 , "bst":0.055, "miss":6, "meetR":0.9988},
  "fifo_ms": { "avg":0.15, "wst":1.8 , "bst":0.067, "miss":0, "meetR":1}
},
"inheritance": "PASS"
}

תוצאות הבדיקה האלה מציגות את הפרטים הבאים:

"pair":3
יצירת צמד אחד של לקוח ושרת.
"iterations": 5000
כולל 5,000 איטרציות.
"deadline_us":2500
המועד האחרון: 2,500 ש"ח (2.5 אלפיות השנייה); רוב העסקאות צפויות לעמוד עם ערך מסוים.
"I": 10000
איטרציה אחת של בדיקה כוללת שתי (2) עסקאות:
  • עסקה אחת בעדיפות רגילה (CFS other)
  • עסקה אחת לפי עדיפות בזמן אמת (RT-fifo)
5,000 איטרציות שווה ל-10,000 עסקאות.
"S": 9352
9352 מהעסקאות מסונכרנות באותו מעבד (CPU).
"R": 0.9352
מציין את היחס שבו הלקוח והשרת מסונכרנים יחד ב- אותו מעבד (CPU).
"other_ms":{ "avg":0.2 , "wst":2.8 , "bst":0.053, "miss":2, "meetR":0.9996}
הממוצע (avg), הגרוע ביותר (wst) והטוב ביותר (bst) מקרה לדוגמה עבור כל העסקאות שבוצעו על ידי מתקשר רגיל בעדיפות גבוהה. שתי עסקאות missהמועד האחרון למעבר, ולכן היחס עומד (meetR) 0.9996.
"fifo_ms": { "avg":0.16, "wst":1.5 , "bst":0.067, "miss":0, "meetR":1}
דומה ל-other_ms, אך עבור עסקאות שהונפקו על ידי לקוח עם עדיפות rt_fifo. סביר להניח (אבל לא נדרש) התוצאה של fifo_ms טובה יותר מזו של other_ms, עם תוצאה נמוכה יותר הערכים avg ו-wst וערך גבוה יותר ב-meetR (ההבדל יכול להיות משמעותי עוד יותר כאשר הטעינה ברקע).

הערה: טעינה ברקע עשויה להשפיע על התפוקה ואת ההתפלגות other_ms בבדיקת זמן האחזור. רק יכול להיות שיוצגו תוצאות דומות ב-fifo_ms כל עוד הטעינה ברקע בעדיפות נמוכה יותר מ-RT-fifo.

ציון ערכי ההתאמה

כל תהליך לקוח מותאם לתהליך שרת ייעודי עבור הלקוח, ואפשר לתזמן כל צמד בנפרד לכל מעבד (CPU). לעומת זאת, לא אמורה להתרחש העברה במהלך עסקה כל עוד הסימון 'סנכרון' honor

ודאו שהמערכת לא עמוסה מדי! בזמן אחזור ארוך בעומס יתר צפויות תוצאות, תוצאות הבדיקה של מערכת בעומס יתר לא מספקות מידע. כדי לבדוק מערכת עם לחץ גבוה יותר, צריך להשתמש ב--pair #cpu-1 (או ב--pair #cpu בזהירות). בדיקה באמצעות -pair n עם n > #cpu עומס יתר או יוצרת מידע לא שימושי.

ציון ערכי המועד האחרון

לאחר בדיקה נרחבת של תרחיש משתמשים (הרצת הבדיקה של זמן האחזור על מוצר שעומד בדרישות), קבענו שהמועד האחרון להיפגש הוא 2.5 אלפיות השנייה. חדשים שיש להן דרישות גבוהות יותר (למשל 1,000 תמונות לשנייה), ערך המועד האחרון ישתנה.

ציון פלט מפורט

אם תשתמשו באפשרות -v, יוצג פלט מפורט. דוגמה:

libhwbinder_latency -i 1 -v

-------------------------------------------------- service pid: 8674 tid: 8674 cpu: 1 SCHED_OTHER 0
-------------------------------------------------- main pid: 8673 tid: 8673 cpu: 1 -------------------------------------------------- client pid: 8677 tid: 8677 cpu: 0 SCHED_OTHER 0
-------------------------------------------------- fifo-caller pid: 8677 tid: 8678 cpu: 0 SCHED_FIFO 99 -------------------------------------------------- hwbinder pid: 8674 tid: 8676 cpu: 0 ??? 99
-------------------------------------------------- other-caller pid: 8677 tid: 8677 cpu: 0 SCHED_OTHER 0 -------------------------------------------------- hwbinder pid: 8674 tid: 8676 cpu: 0 SCHED_OTHER 0
  • שרשור השירות נוצר עם בעדיפות SCHED_OTHER והפעלה בCPU:1 עם pid 8674.
  • לאחר מכן, העסקה הראשונה מתחילה על ידי fifo-caller. כדי לטפל בעסקה הזו, hwbinder משדרג את עדיפות השרת (pid: 8674 tid: 8676) תהיה 99, וגם מסמן אותה. עם מחלקה של תזמון זמני (מודפס כ-???). הכלי לתזמון ואז מעביר את תהליך השרת ב-CPU:0 כדי לרוץ ומסנכרן אותו עם אותו מעבד (CPU) עם הלקוח.
  • למבצע הקריאה החוזרת (caller) של העסקה השנייה יש עדיפות SCHED_OTHER. השרת משדרג לאחור את עצמו ומספק שירותים מתקשר עם עדיפות SCHED_OTHER.

שימוש במעקב לניפוי באגים

אפשר להגדיר את האפשרות -trace לניפוי באגים בבעיות זמן אחזור. מתי נעשה בו שימוש, בדיקת זמן האחזור מפסיקה את ההקלטה של יומן המעקב ברגע שבו היא מזוהה זמן אחזור. דוגמה:

atrace --async_start -b 8000 -c sched idle workq binder_driver sync freq
libhwbinder_latency -deadline_us 50000 -trace -i 50000 -pair 3
deadline triggered: halt ∓ stop trace
log:/sys/kernel/debug/tracing/trace

הרכיבים הבאים יכולים להשפיע על זמן האחזור:

  • מצב build של Android. מצב Eng הוא בדרך כלל איטי יותר מ- במצב ניפוי באגים ברמת המשתמש.
  • Framework. איך שירות framework משתמש ioctl להגדיר את ה-Binger?
  • Binder Manager (מנהל התקן). האם הנהג תומך ברמת פירוט גבוהה מתבצעת נעילה? האם הגרסה כוללת את כל התיקונים לשיפור הביצועים?
  • גרסת ליבה. הליבה (kernel) של היכולת בזמן אמת טובה יותר כך התוצאות יהיו טובות יותר.
  • הגדרת ליבה. האם הגדרת הליבה כוללת DEBUG הגדרות כמו DEBUG_PREEMPT ו DEBUG_SPIN_LOCK?
  • תזמון ליבה. האם בליבה יש בקרת אנרגיה מתזמנים (EAS) או מתזמן רב-תהליכים הטרוגני (HMP)? ביצוע ליבה (kernel) כלשהי נהגים (נהג/ת cpu-freq, נהג/ת cpu-idle, cpu-hotplug, וכו') להשפיע על המתזמנים?