במסמך הזה נסביר איך לזהות ולפתור בעיות מרכזיות בביצועים של האפליקציה.
בעיות עיקריות בביצועים
יש הרבה בעיות שיכולות לגרום לביצועים גרועים באפליקציה, אבל אלה כמה בעיות נפוצות שכדאי לחפש:
- זמן האחזור של ההפעלה
זמן האחזור של ההפעלה הוא משך הזמן שחולף בין הקשה על סמל האפליקציה, על ההתראה או על נקודת כניסה אחרת, לבין הצגת הנתונים של המשתמש במסך.
כדאי להגדיר באפליקציות את יעדי ההפעלה הבאים:
- הפעלה במצב התחלתי (cold start) בפחות מ-500 אלפיות השנייה. הפעלה במצב התחלתי (cold start) מתרחשת כשהאפליקציה שמופעלת לא נמצאת בזיכרון של המערכת. זה קורה כשזו הפעם הראשונה שהאפליקציה מופעלת מאז הפעלה מחדש או מאז שתהליך האפליקציה נעצר על ידי המשתמש או המערכת. הפעלה במצב התחלתי דורשת הכי הרבה עבודה מהמערכת, כי היא צריכה לטעון הכול מהאחסון ולאתחל את האפליקציה. כדאי לנסות להקטין את משך הזמן של הפעלה במצב התחלתי ל-500 אלפיות השנייה או פחות.
- הפעלה במצב ביניים (Warm start) תוך פחות מ-200 אלפיות השנייה והפעלה מתוך הזיכרון (Hot start) תוך פחות מ-150 אלפיות השנייה. הפעלה מהירה מתרחשת כשהתהליך של האפליקציה כבר פועל ברקע, אבל המערכת צריכה לאתחל מחדש את ממשק המשתמש או להחזיר את הפעילות לחזית, למשל כשמשתמש יוצא מהאפליקציה ופותח אותה מחדש זמן קצר לאחר מכן. הפעלה מתוך הזיכרון (Hot start) היא אפילו מהירה יותר כי הפעילות של האפליקציה כבר נשמרה במטמון בזיכרון, וצריך רק להעביר אותה לחזית, בלי ליצור מחדש את היררכיית התצוגה. מומלץ לשאוף לכך שזמני ההפעלה החמים יהיו מתחת ל-200 אלפיות השנייה, וזמני ההפעלה הקרים יהיו מתחת ל-150 אלפיות השנייה.
- זמני האחזור P95 ו-P99 קרובים מאוד לזמן האחזור החציוני. הערכים P95 ו-P99 מייצגים את האחוזון ה-95 וה-99 של זמני ההפעלה, והערך החציוני הוא האחוזון ה-50. אם האפליקציה נטענת לאט, חוויית המשתמש נפגעת. תקשורת בין תהליכים (IPC) וקלט/פלט (I/O) מיותרים במהלך הנתיב הקריטי של הפעלת האפליקציה עלולים לגרום למחלוקת על נעילה ולהוביל לחוסר עקביות.
- גלילה לא חלקה
Jank הוא המונח שמתאר את הבעיה החזותית שמתרחשת כשהמערכת לא מצליחה ליצור ולספק פריימים בזמן כדי לצייר אותם על המסך בקצב המבוקש של 60 הרץ ומעלה. בעיות בממשק (jank) הכי בולטות בזמן גלילה, כשבמקום אנימציה חלקה יש קפיצות. ג'אנק מופיע כשהתנועה מושהית במהלך הדרך למשך פריים אחד או יותר, כי לאפליקציה לוקח יותר זמן לעבד תוכן מאשר משך הזמן של פריים במערכת.
כדאי לכוון לקצב רענון של 90 הרץ באפליקציות. קצב הרינדור המקובל הוא 60Hz, אבל הרבה מכשירים חדשים יותר פועלים במצב 90Hz במהלך אינטראקציות עם המשתמש, כמו גלילה. יש מכשירים שתומכים בקצב רענון גבוה עוד יותר, עד 120Hz.
כדי לראות באיזה קצב רענון המכשיר משתמש בזמן נתון, מפעילים שכבת-על באמצעות אפשרויות למפתחים > הצגת קצב הרענון בקטע ניפוי באגים.
- מעברים לא חלקים
הדבר בולט במהלך אינטראקציות כמו מעבר בין כרטיסיות או טעינה של פעילות חדשה. מעברים מהסוגים האלה צריכים להיות אנימציות חלקות, ולא לכלול עיכובים או הבהובים חזותיים.
- חוסר יעילות בצריכת החשמל
העבודה מפחיתה את הטעינה של הסוללה ובסופו של דבר את חיי הסוללה.
הקצאות זיכרון, שנובעות מיצירת אובייקטים חדשים בקוד, גורמות לעבודה במערכת. ההקצאות עצמן דורשות מאמץ מ-Android Runtime (ART), וגם שחרור האובייקטים האלה מאוחר יותר (איסוף אשפה) דורש זמן ומאמץ.
הקצאת הזיכרון ומנגנון איסוף הזבל הפכו למהירים ויעילים הרבה יותר, במיוחד עבור אובייקטים זמניים. בעבר, ההמלצה הייתה להימנע מהקצאת אובייקטים ככל האפשר, אבל עכשיו אנחנו ממליצים לעשות את מה שהכי הגיוני לאפליקציה ולארכיטקטורה שלכם. השיטה המומלצת היא לא לחסוך בהקצאות על חשבון קוד שאי אפשר לתחזק, בהתחשב ביכולות של ART.
עם זאת, הקצאות דורשות מאמץ, ולכן חשוב לזכור שהן עלולות לגרום לבעיות בביצועים אם מקצים הרבה אובייקטים בלולאה הפנימית.
זיהוי בעיות
כדי לפתור בעיות בביצועים, צריך לזהות ולבדוק את תהליכי המשתמש הקריטיים הבאים:
- תהליכי הפעלה נפוצים, כולל מהמפעיל ומההתראה.
- מסכים שבהם המשתמש גולל נתונים.
- מעברים בין מסכים.
- תהליכים ארוכים, כמו ניווט או הפעלת מוזיקה.
לכל אחד מהתהליכים האלה, כדאי לבדוק מה קורה באמצעות כלי הניפוי הבאים:
- Perfetto: מאפשר לכם לראות מה קורה בכל המכשיר באמצעות נתוני תזמון מדויקים.
- Memory Profiler: מאפשר לראות אילו הקצאות זיכרון מתבצעות ב-heap.
- Simpleperf: מציג תרשים להבה של קריאות הפונקציות שמשתמשות במעבד הכי הרבה במהלך תקופה מסוימת. אם אתם מזהים ב-Systrace משהו שלוקח הרבה זמן, אבל אתם לא יודעים למה, Simpleperf יכול לספק מידע נוסף.
כדי להבין את בעיות הביצועים האלה ולנפות באגים, חשוב לנפות באגים באופן ידני בהרצות בדיקה ספציפיות. אי אפשר להחליף את השלבים הקודמים בניתוח של נתונים מצטברים. עם זאת, כדי להבין מה המשתמשים רואים בפועל ולזהות מקרים של רגרסיות, חשוב להגדיר איסוף מדדים בבדיקות אוטומטיות ובשטח:
- תהליכי הפעלה
- מדדים מהשטח: זמן ההפעלה של Play Console
- בדיקות מעבדה: בדיקת ההפעלה באמצעות Macrobenchmark
- Jank
- מדדים מהשטח
- מדדים חיוניים של מסגרת Play Console: ב-Play Console אי אפשר לצמצם את המדדים למסלול משתמש ספציפי. הוא מדווח רק על jank כולל באפליקציה.
- מדידה בהתאמה אישית באמצעות
FrameMetricsAggregator: אפשר להשתמש ב-FrameMetricsAggregatorכדי לתעד מדדי jank במהלך תהליך עבודה מסוים.
- בדיקות מעבדה
- גלילה באמצעות Macrobenchmark.
- בדיקת ביצועים ברמת המאקרו אוספת נתונים על תזמון הפריימים באמצעות
dumpsys gfxinfoפקודות שמקיפות מסלול משתמש יחיד. כך אפשר להבין את השונות ב-jank לאורך מסלול ספציפי להמרת משתמשים. המדדיםRenderTime, שמדגישים כמה זמן לוקח לצייר את הפריימים, חשובים יותר ממספר הפריימים המקוטעים לצורך זיהוי של רגרסיות או שיפורים.
- מדדים מהשטח
בעיות באימות של קישורים לאפליקציות
קישורים לאפליקציות הם קישורי עומק שמבוססים על כתובת האתר שלכם ומאומתים כשייכים לאתר. אימותים של קישורי אפליקציה עלולים להיכשל מהסיבות הבאות:
- היקפים שגויים של מסנני Intent: מוסיפים רק
autoVerifyלמסנני Intent עבור כתובות URL שהאפליקציה יכולה להגיב להן. - מעברים לא מאומתים בין פרוטוקולים: הפניות אוטומטיות לא מאומתות מצד השרת ומדומיין משנה נחשבות לסיכוני אבטחה, והאימות שלהן נכשל. הם גורמים לכשל בכל הקישורים של
autoVerify. לדוגמה, הפניה אוטומטית של קישורים מ-HTTP ל-HTTPS, כמו מ-example.com ל-www.example.com, בלי לאמת את קישורי ה-HTTPS עלולה לגרום לאימות להיכשל. חשוב לאמת את App Links על ידי הוספת מסנני Intent. - קישורים שלא ניתן לאמת: הוספה של קישורים שלא ניתן לאמת למטרות בדיקה עלולה לגרום למערכת לא לאמת את קישורי האפליקציה עבור האפליקציה שלכם.
- שרתים לא אמינים: מוודאים שהשרתים יכולים להתחבר לאפליקציות הלקוח.
הגדרת האפליקציה לניתוח ביצועים
חשוב להגדיר את הבדיקה בצורה נכונה כדי לקבל מדדים מדויקים, שניתן לחזור עליהם ושניתן לפעול לפיהם. מומלץ לבצע את הבדיקה במערכת שדומה ככל האפשר לסביבת הייצור, תוך ביטול מקורות הרעש. בקטעים הבאים מפורטות כמה פעולות ספציפיות ל-APK ולמערכת שאפשר לבצע כדי להכין את הגדרת הבדיקה. חלק מהפעולות האלה ספציפיות לתרחיש שימוש מסוים.
נקודות מעקב
אפליקציות יכולות להטמיע בקוד שלהן אירועים מותאמים אישית של מעקב.
במהלך הלכידה של העקבות, יש תקורה קטנה של כ-5 מיקרו-שניות לכל קטע, ולכן לא כדאי להשתמש בה סביב כל שיטה. מעקב אחרי חלקים גדולים יותר של עבודה, >0.1ms, יכול לספק תובנות משמעותיות לגבי צווארי בקבוק.
שיקולים לגבי קובץ APK
גרסאות ניפוי הבאגים יכולות לעזור בפתרון בעיות ובסימול של דגימות מחסנית, אבל יש להן השפעות חמורות על הביצועים. במכשירים עם Android מגרסה 10 (רמת API 29) ומעלה, אפשר להשתמש ב-profileable android:shell="true" במניפסט כדי להפעיל פרופילים בגרסאות של אפליקציות שמוכנות להפצה.
משתמשים בהגדרות כיווץ הקוד ברמת הייצור. בהתאם למשאבים שבהם האפליקציה משתמשת, זה יכול להשפיע באופן משמעותי על הביצועים. חלק מההגדרות של ProGuard מסירות נקודות מעקב, לכן כדאי להסיר את הכללים האלה מההגדרה שאתם מריצים עליה בדיקות.
קומפילציה
קומפילציה של האפליקציה במכשיר למצב ידוע – בדרך כלל speed כדי לפשט את התהליך, או speed-profile כדי להתאים יותר לביצועים בסביבת הייצור (אבל זה דורש הפעלה של האפליקציה ופריקה של פרופילים או קומפילציה של פרופילי הבסיס של האפליקציה).
השימוש ב-speed וב-speed-profile מצמצם את כמות הקוד שמופעל בניתוח מ-dex, וכתוצאה מכך את כמות ההידור בזמן ריצה (JIT) ברקע, שעלול לגרום להפרעות משמעותיות. רק speed-profile
מצמצם את ההשפעה של טעינת מחלקות בזמן ריצה מ-dex.
הפקודה הבאה קומפלה את האפליקציה באמצעות מצב speed:
adb shell cmd package compile -m speed -f com.example.packagename
במצב הקומפילציה speed, השיטות של האפליקציה עוברות קומפילציה מלאה. במצב speed-profile, המערכת מבצעת קומפילציה של השיטות והמחלקות של האפליקציה בהתאם לפרופיל של נתיבי הקוד שנעשה בהם שימוש, שנאסף במהלך השימוש באפליקציה. יכול להיות שיהיה לכם קשה לאסוף פרופילים באופן עקבי ונכון, ולכן אם אתם מחליטים להשתמש בהם, חשוב לוודא שהם אוספים את מה שאתם מצפים. הפרופילים נמצאים במיקום הבא:
/data/misc/profiles/ref/[package-name]/primary.prof
שיקולים שקשורים למערכת
כדי לקבל מדידות ברמה נמוכה ובדיוק גבוה, צריך לכייל את המכשירים. הפעלת השוואות A/B באותו מכשיר ובאותה גרסה של מערכת ההפעלה. יכולים להיות הבדלים משמעותיים בביצועים, גם בין מכשירים מאותו סוג.
במכשירים עם הרשאת root, מומלץ להשתמש בסקריפט lockClocks למיקרו-בנצ'מרקים. בין היתר, הסקריפטים האלה מבצעים את הפעולות הבאות:
- הצבת מעבדים בתדר קבוע.
- משביתים ליבות קטנות ומגדירים את ה-GPU.
- השבתה של ויסות נתונים בגלל חום.
לא מומלץ להשתמש בסקריפט lockClocks לבדיקות שמתמקדות בחוויית המשתמש, כמו השקת אפליקציה, בדיקת DoU ובדיקת jank, אבל הוא יכול להיות חיוני לצמצום הרעש בבדיקות Microbenchmark.
אם אפשר, כדאי להשתמש במסגרת בדיקה כמו Macrobenchmark, שיכולה לצמצם את הרעשים במדידות ולמנוע חוסר דיוק במדידות.
הפעלה איטית של האפליקציה: פעילות מיותרת של טרמפולינה
פעילות טרמפולינה עלולה להאריך את זמן ההפעלה של האפליקציה שלא לצורך, ולכן חשוב לדעת אם האפליקציה שלכם מבצעת פעילות כזו. כפי שאפשר לראות בדוגמה הבאה של מעקב, אירוע activityStart אחד מופיע מיד אחרי אירוע activityStart אחר, בלי שפריימים כלשהם מצוירים על ידי הפעילות הראשונה.
איור 1. גרף שמציג את הפעילות בטרמפולינה.
המצב הזה יכול לקרות גם בנקודת כניסה של התראה וגם בנקודת כניסה רגילה של הפעלת אפליקציה, ולרוב אפשר לפתור אותו באמצעות שינוי מבנה הקוד. לדוגמה, אם אתם משתמשים בפעילות הזו כדי לבצע הגדרה לפני הפעלה של פעילות אחרת, כדאי להוציא את הקוד הזה לרכיב או לספרייה שאפשר לעשות בהם שימוש חוזר.
הקצאות מיותרות שמפעילות איסוף אשפה לעיתים קרובות
יכול להיות שתראו ב-Systrace איסוף של נתונים מיותרים (GC) בתדירות גבוהה יותר מהצפוי.
בדוגמה הבאה, מנגנון איסוף זבל כל 10 שניות במהלך פעולה ממושכת הוא אינדיקטור לכך שהאפליקציה עשויה להקצות שלא לצורך, אבל באופן עקבי לאורך זמן:
איור 2. מעקב שמציג את המרווח בין אירועי איסוף האשפה.
יכול להיות שתשימו לב גם בכלי Memory Profiler שרוב ההקצאות מתבצעות על ידי סטאק ביצוע ספציפי. אין צורך להסיר את כל ההקצאות באופן אגרסיבי, כי זה עלול להקשות על תחזוקת הקוד. במקום זאת, כדאי להתחיל לעבוד על נקודות חמות של הקצאות.
פריימים עם בעיות בממשק (jank)
צינור הגרפיקה יחסית מסובך, ויכול להיות שיהיו הבדלים קלים בין המקרים שבהם משתמש יראה בסופו של דבר פריים שהושמט. במקרים מסוימים, הפלטפורמה יכולה 'להציל' פריים באמצעות אחסון בזיכרון זמני (באפרינג). עם זאת, אפשר להתעלם מרוב הניואנסים האלה כדי לזהות פריימים בעייתיים מנקודת המבט של האפליקציה.
כשמציירים פריימים בלי שהאפליקציה נדרשת לעבוד קשה, נקודות המעקב Choreographer.doFrame() מופיעות בקצב של 16.7ms במכשיר עם 60 FPS:
איור 3. מעקב שבו מוצגים פריימים מהירים בתדירות גבוהה.
אם מרחיקים את התצוגה ומתקדמים לאורך ה-trace, לפעמים רואים שפריימים מסוימים לוקחים קצת יותר זמן להשלמה, אבל לא יותר מהזמן שהוקצה להם – 16.7ms. המסגרות האלה תקינות:
איור 4. מעקב שמראה פריימים מהירים בתדירות גבוהה עם פרצי עבודה תקופתיים.
כשרואים שיבוש בקצב הרגיל הזה, מדובר בפריים עם גמגום, כמו שמוצג באיורים 5 ו-6:
איור 5. מעקב שמראה פריים עם תנועה קופצנית.
איור 6. מעקב שמציג יותר פריימים עם תנועות קופצות.
במקרים מסוימים, צריך להתקרב לנקודת מעקב כדי לקבל מידע נוסף על רכיבי ממשק המשתמש שמתעדכנים על ידי Compose, או כמו באיור 6, כדי לראות מה עושה LazyColumn. כשמאבחנים צווארי בקבוק בממשק המשתמש, יכול להיות שמעקב רגיל אחרי המערכת לא יראה אילו רכיבים ניתנים להרכבה הם שורש הבעיה. במקרים כאלה, כדאי להשתמש במעקב אחר קומפוזיציה של Jetpack Compose, שמציג פונקציות קומפוזיציה מדויקות ישירות בנתוני המעקב, וכך קל יותר לזהות קומפוזיציות מחדש לא צפויות. איורים 5 ו-6 מציגים את התוצאות של מעקב אחר קומפוזיציה.
מידע נוסף על אופטימיזציה של הביצועים של Compose זמין במאמר Jetpack Compose Performance. מידע נוסף על זיהוי פריימים עם תנועה קופצנית ועל ניפוי באגים של הגורמים לכך זמין במאמר רינדור איטי.
טעויות נפוצות בפריסת לייאוט עצלנית
ביטול התוקף של כל מצב הגיבוי של פריסה עצלה שלא לצורך עלול להוביל להרכבות מחדש מוגזמות, לזמני רינדור ארוכים של פריימים ולתנודות. כדי לצמצם את מספר הפריטים ברשימה שצריך לעדכן, משתמשים במפתחות פריטים עבור הפריטים ומשנים רק את רכיבי המצב הספציפיים שמשתנים.
במאמר שימוש במקשי פריסה עצלה מוסבר איך להימנע מהקצאות מחדש יקרות של רשימות מלאות, שגורמות לעדכון התוכן במקום להחלפה מלאה שלו.
הטמעה לא תקינה של רשימות גלילה מוטמעות עלולה לגרום לירידה בביצועים. אל תשתמשו בפריסת גלילה עצלה בתוך מאגר גלילה אחר בלי אילוצים מפורשים. מידע נוסף מופיע במאמר בנושא איך נמנעים מהוספת רכיבים שניתנים לגלילה באותו כיוון.
אם לא מתבצעת אחזור מראש של מספיק נתונים, או אם האחזור לא מתבצע בזמן, המשתמשים יצטרכו לחכות לנתונים נוספים מהשרת כשהם יגללו לתחתית של רשימה, וזה עלול להיות מתסכל. למרות שזו לא בעיה טכנית, כי לא חל איחור במועד האחרון של אף פריים, אפשר לשפר משמעותית את חוויית המשתמש על ידי שינוי התזמון והכמות של אחזור מראש, כך שהמשתמש לא יצטרך לחכות לנתונים.
ניפוי באגים באפליקציה
ריכזנו כאן כמה שיטות לניפוי באגים בביצועי האפליקציה.
ניפוי באגים בהפעלת האפליקציה באמצעות Systrace
במאמר זמן ההפעלה של האפליקציה מופיעה סקירה כללית של תהליך הפעלת האפליקציה. בסרטון הבא מופיעה סקירה כללית של מעקב אחר המערכת ושימוש בכלי הפרופיל של Android Studio.
אפשר להבחין בין סוגי סטארטאפים בשלבים הבאים:
- הפעלה במצב התחלתי (cold start): מתחילה ביצירת תהליך חדש ללא מצב שמור.
- הפעלה במצב ביניים (warm startup): הפעילות נוצרת מחדש תוך שימוש חוזר בתהליך, או שהתהליך נוצר מחדש עם המצב השמור.
- הפעלה מתוך הזיכרון (hot startup): הפעלה מחדש של ה-Activity והתחלה ביצירת אובייקט התצוגה.
מומלץ לצלם Systraces באמצעות אפליקציית System Tracing במכשיר. ב-Android מגרסה 10 ואילך, משתמשים ב-Perfetto. ב-Android מגרסה 9 ומטה, משתמשים ב-Systrace. מומלץ גם לצפות בקבצים של פרטי ההעברה באמצעות כלי Perfetto לצפייה בפרטי ההעברה באינטרנט. מידע נוסף מופיע במאמר סקירה כללית על מעקב אחר מערכות.
הנה כמה דברים שכדאי לבדוק:
- מעקב אחרי תחרות על משאבים: תחרות על משאבים שמוגנים על ידי צג יכולה לגרום לעיכוב משמעותי בהפעלת האפליקציה.
טרנזקציות סינכרוניות של binder: כדאי לחפש טרנזקציות מיותרות בנתיב הקריטי של האפליקציה. אם עסקה נדרשת היא יקרה, כדאי לפנות לצוות הפלטפורמה הרלוונטי כדי לבצע שיפורים.
איסוף נתונים במקביל: זה נפוץ יחסית ובעל השפעה נמוכה, אבל אם אתם נתקלים בזה לעיתים קרובות, כדאי לבדוק את זה באמצעות הכלי Memory Profiler של Android Studio.
קלט/פלט (I/O): בודקים אם בוצע קלט/פלט במהלך ההפעלה, ומחפשים עצירות ארוכות.
פעילות משמעותית בשרשורים אחרים: פעילות כזו עלולה להפריע לשרשור UI, לכן חשוב לשים לב לעבודת רקע במהלך ההפעלה.
מומלץ להתקשר אל reportFullyDrawn כשההפעלה מסתיימת מנקודת המבט של האפליקציה, כדי לשפר את הדיווח על מדדי ההפעלה של האפליקציה. מידע נוסף על השימוש ב-reportFullyDrawn זמין בקטע הזמן עד להצגה מלאה.
אפשר לחלץ את זמני ההתחלה שמוגדרים ב-RFD באמצעות מעבד הנתונים של Perfetto trace,
ומופק אירוע trace שגלוי למשתמש.
שימוש במעקב מערכת במכשיר
אפשר להשתמש באפליקציה ברמת המערכת שנקראת System Tracing (מעקב אחר המערכת) כדי לתעד מעקב אחר המערכת במכשיר. האפליקציה הזו מאפשרת להקליט נתונים מהמכשיר בלי לחבר אותו או להתחבר אל adb.
שימוש ב-Memory Profiler ב-Android Studio
אתם יכולים להשתמש בMemory Profiler של Android Studio כדי לבדוק את העומס על הזיכרון, שיכול להיגרם מדליפות זיכרון או מדפוסי שימוש לא טובים. הוא מספק תצוגה בזמן אמת של הקצאות אובייקטים.
כדי לפתור בעיות שקשורות לזיכרון באפליקציה, אפשר להשתמש בכלי Memory Profiler כדי לעקוב אחרי הסיבות לכך ש-GC מתרחש ואחרי התדירות שבה הוא מתרחש.
כדי ליצור פרופיל של זיכרון האפליקציה, פועלים לפי השלבים הבאים:
זיהוי בעיות בזיכרון.
מקליטים סשן של פרופיל זיכרון של התהליך שהמשתמש עובר שבו רוצים להתמקד. מחפשים עלייה במספר האובייקטים, כמו שמוצג באיור 7, שמובילה בסופו של דבר לאיסוף נתונים, כמו שמוצג באיור 8.
איור 7. הגדלת מספר האובייקטים.
איור 8. איסוף אשפה.אחרי שמזהים את מסלול המשתמש שגורם ללחץ על הזיכרון, מנתחים את שורשי הבעיה של הלחץ על הזיכרון.
אבחון נקודות חמות של עומס על הזיכרון.
בוחרים טווח בציר הזמן כדי להציג את ההקצאות ואת הגודל הרדוד, כמו שמוצג באיור 9.
איור 9. הערכים של Allocations ו-Shallow
Size.יש כמה דרכים למיין את הנתונים האלה. הנה כמה דוגמאות לאופן שבו כל תצוגה יכולה לעזור לכם לנתח בעיות.
סידור לפי כיתה: שימושי כשרוצים למצוא כיתות שמייצרות אובייקטים שאחרת נשמרים במטמון או נעשה בהם שימוש חוזר ממאגר זיכרון.
לדוגמה, אם אפליקציה יוצרת 2,000 אובייקטים מסוג מסוים בכל שנייה, המספר של ההקצאות גדל ב-2,000 בכל שנייה, ואפשר לראות את זה כשממיינים לפי סוג. אם רוצים לעשות שימוש חוזר באובייקטים האלה כדי להימנע מיצירת נתונים מיותרים, צריך להטמיע מאגר זיכרון.
סידור לפי מחסנית קריאות: שימושי כשרוצים לגלות איפה יש נתיב חם שבו מוקצה זיכרון, למשל בתוך לולאה או בתוך פונקציה ספציפית שמבצעת הרבה עבודת הקצאה.
גודל שטחי: רק הזיכרון של האובייקט עצמו. היא שימושית למעקב אחרי מחלקות פשוטות שמורכבות בעיקר מערכים פרימיטיביים.
גודל שמור: הגודל הכולל של הזיכרון בגלל האובייקט עצמו, בתוספת הפניות שמופנות רק לאובייקט. הוא שימושי למעקב אחרי עומס על הזיכרון בגלל אובייקטים מורכבים. כדי לקבל את הערך הזה, צריך לבצע dump מלא של הזיכרון, כמו שמוצג באיור 10. העמודה הגודל נשמר נוספת, כמו שמוצג באיור 11.
איור 10. פריקת זיכרון מלאה.
איור 11. בעמודה 'הנפח שמתפנה'.
מדידת ההשפעה של אופטימיזציה.
קל יותר לראות את ה-GC ולמדוד את ההשפעה של האופטימיזציות בזיכרון. כשפעולת אופטימיזציה מפחיתה את העומס על הזיכרון, רואים פחות איסוף נתונים.
כדי למדוד את ההשפעה של האופטימיזציה, בטיימליין של כלי הפרופיל, מודדים את הזמן בין איסופי האשפה. השפעה חיובית מובילה לפרק זמן ארוך יותר בין איסופי האשפה.
ההשפעות הסופיות של שיפורי הזיכרון הן:
- אם האפליקציה לא מגיעה כל הזמן למצב של עומס על הזיכרון, סביר להניח שמקרים של כיבוי בגלל חוסר מקום בזיכרון יפחתו.
- כשיש פחות איסוף נתונים, מדדי ה-jank משתפרים, במיוחד ב-P99. הסיבה לכך היא ש-GC גורם למאבק על המעבד, מה שעלול להוביל לדחייה של משימות רינדור בזמן שמתבצע GC.
מומלץ בשבילכם
- הערה: טקסט הקישור מוצג כש-JavaScript מושבת
- ניתוח ואופטימיזציה של הפעלת אפליקציות {:#app-startup-analysis-optimization}
- פריימים קפואים
- כתיבת Macrobenchmark