בדיקת מעקבים

בתצוגת המעקב בכלי ליצירת פרופילים של CPU יש כמה דרכים להצגת מידע ממעקבים מתועדים.

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

מקשי קיצור בעכבר ובמקלדת זמינים כדי לנווט בקלות בתרשימי שיחות או במעקב אחר אירועים.

בדיקת עקבות באמצעות תרשים השיחות

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

איור 1. תרשים לדוגמה של שיחות שממחיש את הזמן של עצמו, של הילדים והזמן הכולל של שיטה D.

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

בדיקת עקבות באמצעות הכרטיסייה Flame Chart

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

כדי להמחיש את הרעיון הזה, אפשר לעיין בתרשים השיחות באיור 2. שימו לב שה-method D שולח כמה קריאות ל-method B‏ (B1,‏ B2 ו-B3), וחלק מהקריאות האלה ל-method B שולחות קריאה ל-method C‏ (C1 ו-C3).

איור 2. תרשים של שיחות עם כמה קריאות לשיטות שמשותפות ברצף משותף של מתקשרים.

מכיוון של-B1, ‏ B2 ו-B3 יש את אותו רצף של קריאות (A → D → B), הן מצטברות, כפי שמוצג באיור 3. באופן דומה, C1 ו-C3 מצטברים כי יש להם את אותו רצף של מתקשרים (A → D → B → C). שימו לב ש-C2 לא נכלל כי יש לו רצף שונה של מתקשרים (A → D → C).

איור 3. צבירה של שיטות זהות שחולקות את אותו מחסנית קריאות.

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

איור 4. תרשים להבה שמייצג את תרשים השיחות שמוצג באיור 5.

בדיקת עקבות באמצעות Top Down ו-Bottom Up

בכרטיסייה מלמעלה למטה מוצגת רשימה של קריאות. כשמרחיבים צומת של שיטה או פונקציה, מוצגות הפונקציות שנקראו. איור 5 מציג תרשים מלמעלה למטה של תרשים השיחות באיור 1. כל חץ בתרשים מצביע מהמתקשר אל מקבל השיחה.

כפי שמוצג באיור 5, הרחבת הצומת של שיטה א' בכרטיסייה מלמעלה למטה מציגה את השיטות שנקראות על ידה, שיטה ב' ושיטה ד'. אחרי זה, כשמרחיבים את הצומת של שיטה D, נחשפות השיטות שנקראות על ידה, שיטות B ו-C, וכן הלאה. בדומה לכרטיסייה תרשים הלהבה, העץ מלמעלה למטה צובר מידע על מעקב אחר שיטות זהות שמשתמשות באותו מחסנית קריאות. כלומר, הכרטיסייה תרשים הלהבה מספקת ייצוג גרפי של הכרטיסייה מלמעלה למטה.

בכרטיסייה מלמעלה למטה מופיע המידע הבא שיעזור לכם להבין כמה זמן מעבד (CPU) הושקע בכל שיחה (הזמנים מוצגים גם כאחוז מהזמן הכולל של השרשור בטווח שנבחר):

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

איור 5. עץ מלמעלה למטה.

איור 6. עץ מלמטה למעלה של שיטה C מתוך איור 5.

בכרטיסייה Bottom Up מוצגת רשימה של שיחות. כשמרחיבים את הצומת של פונקציה או שיטה, מוצגים המתקשרים שלה. בדוגמה של עקבות הביצוע שמוצגת באיור 5, באיור 6 מוצג עץ מלמטה למעלה של השיטה C. כשפותחים את הצומת של שיטה C בעץ מלמטה למעלה, מוצגים כל המתקשרים הייחודיים שלה, שיטות B ו-D. הערה: למרות ש-B קורא ל-C פעמיים, B מופיע רק פעם אחת כשמרחיבים את הצומת של השיטה C בעץ מלמטה למעלה. אחרי כן, הרחבת הצומת של B מציגה את המתקשר שלו, שיטות A ו-D.

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

עצמי ילדים סה"כ
ה-method או הפונקציה בראש העץ מלמטה למעלה (הצומת העליון) מייצג את הזמן הכולל שה-method או הפונקציה השקיעו בהרצת הקוד שלהן, ולא של הפונקציות שהן קוראות להן. בהשוואה לעץ מלמעלה למטה, נתוני התזמון האלה מייצגים סכום של כל הקריאות לשיטה או לפונקציה הזו במהלך ההקלטה. מייצג את הזמן הכולל שהוקצה לביצוע של ה-method או הפונקציה, כולל הפונקציות שהיא קוראת להן ולא הקוד שלה. בהשוואה לעץ מלמעלה למטה, מידע התזמון הזה מייצג את סכום כל הקריאות לשיטה או לפונקציה הזו במשך משך ההקלטה. סכום הזמן שלכם ושל הילדים.
מתקשרים (צמתי משנה) מייצג את הזמן הכולל של הפונקציה שנקראה בזמן שהמתקשר קרא לה. בדוגמה של עץ מלמטה למעלה באיור 6, הזמן העצמי של שיטה B יהיה שווה לסכום הזמנים העצמיים של כל הרצה של שיטה C כשמפעילים אותה מ-B. מייצג את משך הזמן הכולל של הילדים של מקבל השיחה בזמן שהשיחה מתבצעת על ידי המתקשר. אם משתמשים בעץ מלמטה למעלה באיור 6 כדוגמה, זמן הצאצא של שיטה B יהיה שווה לסכום של זמני הצאצא של כל הרצה של שיטה C כשקוראים לה מ-B. סכום הזמן שלכם ושל הילדים.

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

בדיקת עקבות באמצעות טבלת האירועים

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

איור 7. צפייה בכרטיסייה 'אירועים' בחלונית הניתוח.

בדיקת מסגרות של מחסנית קריאות

מחסניות קריאות שימושיות כדי להבין איזה חלק בקוד בוצע, ולמה הוא הופעל. אם נאסף Callstack Sample Recording עבור תוכנית Java/Kotlin, בדרך כלל ה-callstack כולל לא רק קוד Java/Kotlin, אלא גם פריימים מקוד JNI מקורי, מכונה וירטואלית של Java (לדוגמה, ‫android::AndroidRuntime::start) וליבת המערכת ([kernel.kallsyms]+offset). הסיבה לכך היא שתוכנית Java/Kotlin בדרך כלל מופעלת דרך מכונה וירטואלית של Java. נדרש קוד מקורי כדי להפעיל את התוכנית עצמה וכדי שהתוכנית תוכל לתקשר עם המערכת והחומרה. הפרופילר מציג את המסגרות האלה כדי לספק דיוק, אבל יכול להיות שהמסגרות הנוספות האלה לא יהיו שימושיות לכם, בהתאם לבדיקה שאתם מבצעים. הכלי לניתוח פרופילים מאפשר לכווץ מסגרות שלא מעניינות אתכם, כדי להסתיר מידע שלא רלוונטי לבדיקה שלכם.

בדוגמה שלמטה, למעקב יש הרבה פריימים עם התווית [kernel.kallsyms]+offset, שלא מועילים כרגע לפיתוח.

דוגמה למעקב אחר שיחה

כדי לכווץ את המסגרות האלה למסגרת אחת, לוחצים על הלחצן כיווץ מסגרות בסרגל הכלים, בוחרים את הנתיבים לכיווץ ולוחצים על הלחצן החלה כדי להחיל את השינויים. בדוגמה הזו, הנתיב הוא [kernel.kallsyms].

דוגמה לתפריט של simpleperf

פעולה כזו תכווץ את המסגרות שמתאימות לנתיב שנבחר בחלוניות הימנית והשמאלית, כמו שמוצג בהמשך.

דוגמה למסגרות מכווצות של simpleperf

בדיקת נתוני מעקב של המערכת

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

בדיקת נתוני מעקב של המערכת: ליבות המעבד

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

איור 8. צפייה בפעילות המעבד ובאירועים של מעקב אחר השרשור של הרינדור.

בחלונית CPU Cores (כפי שמוצג באיור 8) מוצגת פעילות השרשור שתוזמנה בכל ליבה. מעבירים את סמן העכבר מעל פעילות בשרשור כדי לראות באיזה שרשור הליבה הזו פועלת באותו זמן.

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

בדיקת נתוני מעקב של המערכת: ציר זמן של רינדור פריימים

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

בדיקת נתוני מעקב של המערכת: זיכרון התהליך (RSS)

באפליקציות שמופעלות במכשירים עם Android מגרסה 9 ואילך, בקטע Process Memory (RSS) מוצגת כמות הזיכרון הפיזי שמשמשת כרגע את האפליקציה.

איור 9. הצגת הזיכרון הפיזי בפרופיל.

סה"כ

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

למפתחי Windows, גודל קבוצת התושבים דומה לגודל קבוצת העבודה.

הוקצה

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

מיפוי קבצים

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

משותף

המונה הזה עוקב אחרי נפח הזיכרון הפיזי שמשמש לשיתוף זיכרון בין התהליך הזה לבין תהליכים אחרים במערכת.