בדיקת השימוש בזיכרון של האפליקציה באמצעות Memory Profiler

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

כדי לפתוח את ה-Memory Profiler, פועלים לפי השלבים הבאים:

  1. לוחצים על תצוגה > Windows בכלי > הכלי לניתוח פרופילים (אפשר גם ללחוץ על פרופיל בסרגל הכלים).
  2. במכשיר Android, בוחרים את המכשיר ואת תהליך האפליקציה שרוצים ליצור מהם פרופיל. סרגל הכלים של הכלי לפרופיל. אם חיברתם מכשיר באמצעות USB אבל אתם לא רואים אותו רשום, צריך לוודא האפשרות 'ניפוי באגים ב-USB' מופעלת.
  3. לוחצים במקום כלשהו בציר הזמן MEMORY כדי לפתוח את הכלי לפרופיל הזיכרון.

לחלופין, אפשר לבדוק את זיכרון האפליקציה משורת הפקודה עם dumpsys, וגם לצפייה באירועי GC ב-Logcat

למה כדאי ליצור פרופילים לזיכרון האפליקציה

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

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

כדי למנוע בעיות כאלה, מומלץ להשתמש ב'פרופיל הזיכרון' כדי לבצע הבאים:

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

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

סקירה כללית של הכלי לניתוח ביצועי הזיכרון

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

איור 1. הכלי לניתוח הזיכרון

כפי שצוין באיור 1, תצוגת ברירת המחדל של הכלי לפרופיל הזיכרון כוללת את הבאים:

  1. לחצן לאילוץ אירוע איסוף אשפה.
  2. לחצן לצילום תמונת מצב של הזיכרון.

    הערה: לחצן להקלטת זיכרון הקצאות יופיעו משמאל ללחצן של תמונת מצב של הזיכרון רק שמחובר למכשיר עם Android מגרסה 7.1 (רמת API 25) ומטה.

  3. תפריט נפתח שמציין באיזו תדירות הכלי לניתוח ביצועים מצלם את הזיכרון והקצאות אחרות. בחירה באפשרות המתאימה עשויה לעזור לך שיפור ביצועי האפליקציה תוך כדי פרופיילינג.
  4. לחצנים להגדלה או להקטנה של ציר הזמן.
  5. לחצן למעבר קדימה לנתוני הזיכרון בזמן אמת.
  6. ציר הזמן של האירועים, שבו מוצגים מצבי הפעילות, אירועי קלט של משתמשים של סיבוב המסך.
  7. הזיכרון משתמש בציר הזמן, שכולל את הדברים הבאים:
    • גרף מוערם של נפח הזיכרון שנוצל בכל קטגוריית זיכרון, כפי שמצוין בציר ה-Y משמאל ובמקש הצבע למעלה.
    • קו מקווקו מציין את מספר האובייקטים שהוקצו, כפי שצוין בציר ה-Y מימין.
    • סמל של כל אירוע של איסוף אשפה.

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

  • לוח הזמנים של האירוע
  • מספר האובייקטים שהוקצו
  • אירועים בנושא איסוף אשפה

ב-Android מגרסה 8.0 ואילך, הפרופיילינג המתקדם תמיד מופעל לצורך ניפוי באגים באפליקציות.

איך הזיכרון נספר

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

איור 2. מקרא לספירת הזיכרון בחלק העליון של הכלי לניתוח הזיכרון

הקטגוריות בספירת הזיכרון הן:

  • Java: זיכרון מאובייקטים שהוקצו מקוד Java או Kotlin.
  • מקורי: זיכרון מאובייקטים שהוקצו מקוד C או C++.

    גם אם אתם לא משתמשים ב-C++ באפליקציה שלכם, יכול להיות שתראו זיכרון מקורי מסוים כאן כי ה-framework של Android משתמש בזיכרון מקורי כדי משימות שונות בשמך, למשל בזמן טיפול בנכסי תמונות גרפי - למרות שהקוד שכתבת הוא ב-Java או Kotlin.

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

  • מקבץ: הזיכרון המשמש גם את סטאק התוכנות המקורי וגם את סטאק ה-Java באפליקציה. הזה בדרך כלל קשור למספר השרשורים שהאפליקציה פועלת.

  • Code (קוד): הזיכרון שבו האפליקציה משתמשת לקוד ולמשאבים, כמו dex bytecode, קוד dex שעבר אופטימיזציה או הידור, ספריות .so וגופנים.

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

  • הוקצו: מספר האובייקטים של Java/Kotlin שהוקצו על ידי האפליקציה. הוא לא סופר אובייקטים שהוקצו ב-C או ב-C++.

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

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

הצגה של הקצאות הזיכרון

הקצאות זיכרון מראות איך כל אובייקט Java והפניה של JNI בקובץ לזיכרון שהוקצו. באופן ספציפי, הכלי לפרופיל הזיכרון יכול להראות לך הבא על הקצאות אובייקטים:

  • אילו סוגי אובייקטים הוקצו וכמה מקום הם תופסים.
  • דוח קריסות של כל הקצאה, כולל באיזה שרשור.
  • מועד הקצאת האובייקטים (רק כשמשתמשים במכשיר עם Android 8.0) ומעלה).

כדי להקליט הקצאות Java ו-Kotlin, בוחרים תיעוד הקצאות Java / Kotlin, ובוחרים באפשרות Record (הקלטה). אם במכשיר פועלת מערכת Android מגרסה 8 ואילך, ממשק המשתמש של הכלי לניתוח ביצועי הזיכרון עובר למסך נפרד שבו מוצגת מוקלטת. אפשר לבצע פעולות באמצעות ציר הזמן הקצר שמעל ההקלטה (לדוגמה, כדי לשנות את טווח הבחירה). כדי להשלים את ההקלטה: בוחרים באפשרות הפסקה .

תצוגה חזותית של הקצאות Java ב-Memory Profiler

ב-Android 7.1 ומטה, הכלי ליצירת זיכרון משתמש בהקצאה מדור קודם הקלטה, שבה ההקלטה מוצגת בציר הזמן עד שלוחצים Stop

אחרי שבוחרים אזור מציר הזמן (או כשמסיימים הקלטה). במכשיר עם Android מגרסה 7.1 ומטה), רשימת האובייקטים מופיעים, מקובצים לפי שם הכיתה וממוינים לפי מספר ערימה (heap count).

כדי לבדוק את רשומת ההקצאה, פועלים לפי השלבים הבאים:

  1. מעיינים ברשימה כדי למצוא אובייקטים עם מספר ערימה גדול במיוחד שעשויה להדליף. כדי למצוא כיתות ידועות, לוחצים על שם הכיתה כדי למיין את הנתונים לפי סדר אלפביתי. לאחר מכן לוחצים על שם הכיתה. החלונית תצוגת מכונה מופיעה בצד שמאל ומוצגת בה כל מופע של הכיתה, כפי שמוצג באיור 3.
    • אפשר גם ללחוץ על סינון כדי לאתר אובייקטים במהירות. , או על ידי הקשה על Control+F (Command+F ב-Mac) והזנת מחלקה או חבילה השם בשדה החיפוש. אפשר גם לחפש לפי שם השיטה אם בוחרים סדרו לפי פונקציית ה-calltack בתפריט הנפתח. אם רוצים להשתמש בגרסה הרגילה מסמנים את התיבה שלצד Regex. מסמנים את התיבה שלצד התאמה של אותיות רישיות (case-sensitive) אם שאילתת החיפוש היא תלוית אותיות רישיות.
  2. לוחצים על מופע בחלונית Instance View. הכרטיסייה מקבץ שיחות שמופיעה למטה, ומראה איפה הוקצתה המופע ואיזה שרשור.
  3. בכרטיסייה Call Stack, לוחצים לחיצה ימנית על שורה כלשהי ובוחרים בה. מעבר אל המקור כדי לפתוח את הקוד בעורך.

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

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

בתפריט שמימין, בוחרים את תמונת הערימה שרוצים לבדוק:

  • ברירת מחדל של ערימה (heap): אם המערכת לא מציינת שום ערימה (heap).
  • image heap: קובץ האימג' של האתחול של המערכת, המכיל מחלקות שנטענה מראש בזמן האתחול. מובטחות שההקצאות כאן לא יזוזו אף פעם או ללכת לאיבוד.
  • זיגוט ערימה (zygote): הערימה להעתקה-כתיבה שממנה נשלף תהליך של אפליקציה במערכת Android.
  • ערימה של אפליקציה: הערימה הראשית שאליה האפליקציה מקצה זיכרון.
  • ערימה של JNI: הערימה שמציגה איפה Java Native Interface (JNI) ההקצאה ושחרור של הפניות.

בתפריט שמשמאל, בוחרים איך לארגן את ההקצאות:

  • סידור לפי כיתה: קיבוץ כל ההקצאות לפי שם הכיתה. הדבר ברירת המחדל.
  • סידור לפי חבילה: קיבוץ כל ההקצאות לפי שם החבילה.
  • סידור לפי ערימה (calltack): קיבוץ כל ההקצאות לפי מקבץ שיחות.

שיפור ביצועי האפליקציה תוך כדי יצירת הפרופיל

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

  • מלא: תיעוד כל הקצאות האובייקטים בזיכרון. זוהי ברירת המחדל ב-Android Studio 3.2 ובגרסאות קודמות. אם יש לכם אפליקציה שמגדירה הרבה אובייקטים, אולי תבחינו בהאטות גלויות בזמן יצירת הפרופיילינג.
  • נדגם: דגימות הקצאות אובייקטים בזיכרון במרווחי זמן קבועים. הזה מוגדרת כברירת המחדל, ויש לה פחות השפעה על ביצועי האפליקציה פרופיילינג. אפליקציות שמוקצות כמות גדולה של אובייקטים בפרק זמן קצר עשויות עדיין משקפים האטיות גלויות.
  • כבוי: הפסקת המעקב אחר הקצאת הזיכרון של האפליקציה.

הצגת הפניות גלובליות ל-JNI

Java Native Interface (JNI) הוא framework שמאפשר לקוד Java ול-Native כדי להתקשר אחד לשני.

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

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

בזמן שהאפליקציה פועלת, בוחרים חלק מציר הזמן שרוצים לבדוק ולבחור ערימה של JNI בתפריט הנפתח שמעל רשימת הכיתות. עכשיו אפשר לבדוק את האובייקטים שבערימה כרגיל וללחוץ לחיצה כפולה את האובייקטים בכרטיסייה Allocation Call Stack כדי לראות את המיקום של הפניות ה-JNI שהוקצו ושוחררו בקוד, כפי שמוצג באיור 4.

איור 4. הצגת הפניות JNI גלובלי

כדי לבדוק את הקצאות הזיכרון של קוד ה-JNI של האפליקציה, צריך לפרוס את האפליקציה במכשיר Android מגרסה 8.0 ואילך.

מידע נוסף על JNI זמין במאמר טיפים בנושא JNI.

כלי לניתוח נתוני זיכרון נייטיב

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

ה-Native Memory Profiler עוקב אחרי הקצאות או הקצאות של אובייקטים קוד לתקופה ספציפית, ומספק את המידע הבא:

  • הקצאות: מספר האובייקטים שהוקצו באמצעות malloc() או new במהלך תקופת הזמן שנבחרה.
  • הקצאות מיקום: מספר האובייקטים שהוקצו דרך free() או האופרטור delete במהלך תקופת הזמן שנבחרה.
  • גודל ההקצאות: הגודל המצטבר בבייטים של כל ההקצאות במהלך לפרק הזמן שנבחר.
  • גודל עסקאות: הגודל המצטבר בבייטים של כל הזיכרון שהתפנה במהלך תקופת הזמן שנבחרה.
  • Total count (ספירה כוללת): הערך בעמודה Allocations (הקצאות) בניכוי הערך של בעמודה Deallocations.
  • הגודל שנותר: הערך בעמודה גודל הקצאות בניכוי בעמודה Deallocations size.

כלי לניתוח נתוני זיכרון נייטיב

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

לחצן להקלטת הקצאות מקוריות

ב-Android 9 ומטה, האפשרות הקלטת הקצאות מקוריות לא זמינים.

כברירת מחדל, ה-Native Memory Profiler משתמש בגודל דגימה של 32 בייטים: בכל פעם שמוקצים 32 בייטים מהזיכרון, נוצרת תמונת מצב של הזיכרון. א' דגימה קטנה יותר מובילה לקובצי snapshot תכופים יותר, אשר מניבים נתונים מדויקים על שימוש בזיכרון. דגימה גדולה יותר מניבה פחות דיוק אבל הם יצרוך פחות משאבים במערכת וישתפרו של הביצועים במהלך ההקלטה.

כדי לשנות את גודל הדגימה של Native Memory Profiler:

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

צילום של תמונת מצב של הזיכרון

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

אחרי שמצלמים תמונת מצב של הזיכרון, אפשר לראות את הדברים הבאים:

  • אילו סוגי אובייקטים הקצתה האפליקציה וכמה מכל אחד מהם הקצתה.
  • כמה זיכרון משתמש כל אובייקט.
  • כאשר הפניות לכל אובייקט מוחזקות בקוד.
  • סטאק הקריאות למקום שבו הוקצה האובייקט. (מקבצי שיחות כרגע זמין עם תמונת מצב של הזיכרון רק ב-Android מגרסה 7.1 ומטה כשמצלמים את תמונת מצב של הזיכרון בזמן תיעוד ההקצאות.)

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

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

איור 5. הצגה של תמונת מצב של הזיכרון.

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

ברשימת הכיתות אפשר לראות את הפרטים הבאים:

  • Allocations (הקצאות): מספר ההקצאות בערימה (heap).
  • גודל מותאם: הנפח הכולל של זיכרון מקורי שבו נעשה שימוש בסוג האובייקט הזה (בבייטים). העמודה הזו מוצגת רק ב-Android מגרסה 7.0 ואילך.

    כאן יופיע הזיכרון של חלק מהאובייקטים שהוקצו ב-Java מפני ש-Android משתמש בזיכרון מקורי בחלק ממחלקות ה-framework, Bitmap

  • גודל Shallow: הנפח הכולל של זיכרון Java שמשמש את האובייקט הזה (בבייטים).

  • גודל נשמר: הגודל הכולל של הזיכרון שנשמר בגלל כל המופעים של המחלקה הזו (בבייטים).

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

בתפריט שמימין, בוחרים את תמונת הערימה שרוצים לבדוק:

  • ברירת מחדל של ערימה (heap): אם המערכת לא מציינת שום ערימה (heap).
  • ערימה של אפליקציה: הערימה הראשית שאליה האפליקציה מקצה זיכרון.
  • image heap: קובץ האימג' של האתחול של המערכת, המכיל מחלקות שנטענה מראש בזמן האתחול. מובטחות שההקצאות כאן לא יזוזו אף פעם או ללכת לאיבוד.
  • זיגוט ערימה (zygote): הערימה להעתקה-כתיבה שממנה נשלף תהליך של אפליקציה במערכת Android.

בתפריט שמשמאל, בוחרים איך לארגן את ההקצאות:

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

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

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

  • עומק: המספר הקצר ביותר של צעדים מהשורש של GC אל השורש שנבחר מכונה.
  • Native size (גודל מקורי): הגודל של המכונה הזו בזיכרון הנייטיב. העמודה הזו מוצגת רק ב-Android מגרסה 7.0 ואילך.
  • גודל Shallow: הגודל של המופע הזה בזיכרון Java.
  • RetainedSize: גודל הזיכרון שבו המכונה הזו שולטת (לפי המאפיינים הבאים: עץ הדומינטור).

איור 6. משך הזמן שנדרש לתיעוד ערימה סימן dump מופיע בציר הזמן

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

  1. מעיינים ברשימה כדי למצוא אובייקטים עם מספר ערימה גדול במיוחד שעשויה להדליף. כדי למצוא כיתות ידועות, לוחצים על שם הכיתה כדי למיין את הנתונים לפי סדר אלפביתי. לאחר מכן לוחצים על שם הכיתה. החלונית תצוגת מכונה מופיעה בצד שמאל ומוצגת בה כל מופע של של הכיתה, כפי שמוצג באיור 6.
    • אפשר גם ללחוץ על סינון כדי לאתר אובייקטים במהירות. , או על ידי הקשה על Control+F (Command+F ב-Mac) והזנת מחלקה או חבילה השם בשדה החיפוש. אפשר גם לחפש לפי שם השיטה אם בוחרים סדרו לפי פונקציית ה-calltack בתפריט הנפתח. אם רוצים להשתמש בגרסה הרגילה מסמנים את התיבה שלצד Regex. מסמנים את התיבה שלצד התאמה של אותיות רישיות (case-sensitive) אם שאילתת החיפוש היא תלוית אותיות רישיות.
  2. לוחצים על מופע בחלונית Instance View. קובצי העזר מופיעה למטה, שמציגה את כל ההפניות לאובייקט הזה.

    אפשרות אחרת היא ללחוץ על החץ שליד שם המכונה כדי להציג את כל השדות שלה, ואז ללחוץ על שם של שדה כדי להציג את כל ההפניות שלו. אם רוצים לצפות בפרטי המופע של בשדה מסוים, לוחצים לחיצה ימנית על השדה ובוחרים באפשרות Go to Instance.

  3. בכרטיסייה קובצי עזר, אם אתם מזהים קובץ עזר שעשוי לוחצים לחיצה ימנית ובוחרים באפשרות Go to Instance. פעולה זו בוחרת את המכונה המתאימה מתמונת המצב של הזיכרון, שמציגה את נתוני המכונה שלה.

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

  • הפניות לטווח ארוך אל Activity, Context, View, Drawable ואובייקטים אחרים שעשויים להכיל תג הפניה למאגר Activity או Context.
  • כיתות פנימיות לא סטטיות, כמו Runnable, שיכולות להכיל במופע של Activity.
  • מטמון עם אובייקטים ארוכים מהנדרש.

שמירה של תמונת מצב של הזיכרון כקובץ HPROF

אחרי הצילום של תמונת מצב של הזיכרון, הנתונים גלויים רק ב-Memory Profiler בזמן שמבצע הפרופיל פועל. כאשר יוצאים מהסשן של הפרופיילינג, מאבדים את תמונת מצב של הזיכרון. לכן, כדי לשמור אותו לבדיקה מאוחר יותר, צריך לייצא את תמונת המצב של הזיכרון לקובץ HPROF. ב-Android Studio 3.1 ומטה, לוחצים על ייצוא הצילום לקובץ הלחצן נמצא בצד ימין של סרגל הכלים מתחת לציר הזמן. באזור ב-Android Studio מגרסה 3.2 ואילך, יש לחצן ייצוא תמונת מצב של הזיכרון מימין לכל רשומה של תמונת מצב של הזיכרון בחלונית סשנים. בקטע ייצוא בשם שמופיעה, שומרים את הקובץ עם סיומת שם הקובץ .hprof.

להשתמש בכלי לניתוח נתוני HPROF אחר, כמו jhat, עליך להמיר את קובץ ה-HPROF מפורמט Android לפורמט Java SE HPROF. אפשר לעשות זאת באמצעות הכלי hprof-conv שמסופק הספרייה android_sdk/platform-tools/. הפעלה של hprof-conv פקודה עם שני ארגומנטים: קובץ ה-HPROF המקורי והמיקום לכתיבת ה-HPROF שהומר חדש. לדוגמה:

hprof-conv heap-original.hprof heap-converted.hprof

ייבוא של קובץ של תמונת מצב של הזיכרון

כדי לייבא קובץ HPROF (.hprof), לוחצים על Start a new profileing session (התחלת סשן חדש של פרופיילינג). ב- בחלונית סשנים, בוחרים באפשרות טעינה מקובץ ובוחרים את הקובץ מהקובץ בדפדפן.

ניתן גם לייבא קובץ HPROF על ידי גרירה שלו מדפדפן הקבצים אל חלון העורך.

זיהוי דליפות בכלי לניתוח זיכרון

כשמנתחים תמונת מצב של הזיכרון ב-Memory Profiler, אפשר לסנן את הפרופיילינג נתונים שלפי מערכת Android Studio עשויים להצביע על דליפות זיכרון של Activity וגם Fragment מופעים באפליקציה שלך.

המסנן מציג נתונים מהסוגים הבאים:

  • Activity מכונות נמחקו אבל עדיין יש הפניה אליהן.
  • מופעים של Fragment שאין להם ערך FragmentManager חוקי אבל הם עדיין שיש הפניה אליו.

במצבים מסוימים, כמו במצבים הבאים, המסנן עשוי להניב את הערך False חיובי:

  • Fragment נוצר אבל עדיין לא נעשה בו שימוש.
  • מתבצעת שמירה של Fragment במטמון, אבל לא כחלק מ-FragmentTransaction.

כדי להשתמש בתכונה הזו, קודם צריך לצלם תמונת מצב של הזיכרון או ייבוא קובץ של תמונת מצב של הזיכרון ב-Android Studio. כדי להציג את הסעיפים והפעילויות שעשויים להיות דליפה של זיכרון, צריך לסמן את התיבה דליפות של פעילות/מקטע בערימה. חלונית ה-Dump של ה-Memory Profiler, כפי שמוצג באיור 7.

Profiler: זיהוי דליפת זיכרון

איור 7. סינון של תמונת מצב של הזיכרון לאיתור דליפות זיכרון.

שיטות ליצירת פרופיילינג של הזיכרון

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

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

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

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