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
כלי הוויזואליזציה של המערכת מציג טרנזקציות באופן הבא:
בדוגמה שלמעלה:
- ארבעת (4) התהליכים של schd-dbg הם תהליכי לקוח.
- ארבעת (4) תהליכי החיבור הם תהליכי שרת (השם מתחיל ב- Binder ומסתיים במספר סידורי).
- תהליך לקוח תמיד מותאם לתהליך שרת, שמיועד אל הלקוח שלו.
- כל צמדי התהליכים של לקוח-שרת מתוזמנים באופן עצמאי על ידי ליבה (kernel) בו-זמנית.
ב-CPU 1, הליבה של מערכת ההפעלה מפעילה את הלקוח כדי לשלוח את הבקשה. לאחר מכן משתמשת באותו מעבד (CPU) ככל האפשר כדי להוציא תהליך ממצב שרת, וההקשר החוזר לאחר השלמת הבקשה.
תפוקה לעומת זמן אחזור
בעסקה מושלמת, שבה הלקוח והשרת עוברים עיבוד בצורה חלקה, בדיקות תפוקה וזמן אחזור לא מייצרות הבדלים משמעותיים הודעות. עם זאת, כש הליבה של מערכת ההפעלה מטפלת בבקשת הפרעה (IRQ) מחומרה, בהמתנה למנעולים או פשוט בחירה שלא לטפל בהודעה מיד יכולה להיווצר בועת זמן אחזור.
בדיקת התפוקה יוצרת מספר גדול של עסקאות עם סוגים שונים של גדלים של מטענים ייעודיים (payloads), דבר שמספק הערכה טובה לגבי זמן העסקה הרגיל (ב והתפוקה המקסימלית שכלי הקשר יכול להשיג.
לעומת זאת, הבדיקה של זמן האחזור לא מבצעת פעולות במטען הייעודי (payload) כדי לצמצם במועד הרגיל של העסקה. אנחנו יכולים להשתמש בזמן העסקה כדי להעריך את הקישור ליצור נתונים סטטיסטיים עבור המקרה הגרוע ביותר, ולחשב את היחס עסקאות שזמן האחזור שלהן עומד בתאריך יעד שנקבע.
טיפול בהפוכות בעדיפות
היפוך עדיפות מתרחשת כאשר שרשור עם עדיפות גבוהה יותר נמצא באופן לוגי בהמתנה לשרשור עם עדיפות נמוכה יותר. לאפליקציות בזמן אמת (RT) יש בעיית היפוך עדיפות:
כשמשתמשים בתזמון פגישות הוגן (CFS) של Linux, השרשור תמיד מתחיל ב-thread יכולים לפעול גם אם לשרשורים אחרים יש עדיפות גבוהה יותר. כתוצאה מכך, אפליקציות עם היפוך העדיפות של הטיפול בתזמון CFS, כמצופה ולא כבעיה. במקרים שבהם ל-framework של Android נדרש תזמון RT כדי להבטיח את ההרשאות של שרשורים בעדיפות גבוהה, עם זאת, היפוך עדיפות חייב להיפתר.
דוגמה להיפוך עדיפות במהלך טרנזקציית binder (שרשור RT הוא נחסמו מבחינה לוגית על ידי שרשורי CFS אחרים כשממתינים ל-thread binder ):
כדי להימנע מחסימות, אתם יכולים להשתמש בירושה בעדיפות גבוהה להעברה זמנית לטיפול ברמה גבוהה יותר את ה-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
)
- עסקה אחת בעדיפות רגילה (
"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
, וכו') להשפיע על המתזמנים?