מפות סיביות הן לרוב האובייקטים הכי גדולים שצורכים זיכרון באפליקציה. פעולות של פענוח ושינוי גודל נמצאות לעיתים קרובות בנתיב הקריטי של עיבוד הפריים. אופטימיזציה של השימוש בזיכרון של מפת הסיביות (bitmap) משפרת באופן משמעותי את מהירות התגובה של ממשק המשתמש, את חיי הסוללה ואת היציבות הכוללת, על ידי צמצום בעיות בממשק (jank), שגיאות ANR וסגירת תהליכים שקשורים לשגיאות OOM.
זיהוי שימוש גבוה בזיכרון של מפת הסיביות (bitmap)
בתפקוד האפליקציה מוצגים מדדים לגבי טביעת הרגל של זיכרון מפת הסיביות של האפליקציה, על ידי צבירת נתונים ממכשירי Android. כברירת מחדל, המדדים האלה מחושבים בתור סיכום של נתונים יומיים במשך 28 ימים. הנתונים האלה עוזרים לזהות מגמות ונסיגות פוטנציאליות ביעילות הזיכרון בסוגים ובגרסאות שונים של מכשירים.
בנתונים של מדד תפקוד האפליקציה ב-Android מפורט השימוש בזיכרון של מפת הסיביות (bitmap) באפליקציה לפי מצבי התהליך הבאים:
- חזית: התהליך של האפליקציה גלוי. הערך הצפוי של P99 הוא גבוה משמעותית בפורגראונד לעומת מצבי תהליך אחרים, אבל מפתחים צריכים לבדוק אם היחס בין P99 ל-P50 משמעותי (למשל, גבוה מפי 3.5), כי זה לרוב מצביע על דליפת זיכרון של מפת סיביות. אפשר לזהות את הבעיה הזו על ידי השוואה בין השימוש הטיפוסי (אחוזון 50) לבין השימוש החריג (אחוזון 99). בעוד שנפח נכסים גדול מדי מגדיל את השימוש בזיכרון באופן אחיד בכל האחוזונים, דליפות זיכרון מצטברות לאורך זמן, וגורמות להטיה חזקה בנתונים של הקצה העליון (אחוזון 99). מוודאים שהקצאות של מפות סיביות בחזית לא נשמרות שלא לצורך אחרי שהאפליקציה עוברת למצבים אחרים.
- שירותים שהמשתמשים יכולים לראות: התהליך של האפליקציה פועל במצב גלוי. ההגבלה כוללת שירותים שפועלים ברקע, משימות מואצות ומשימות של העברת נתונים ביוזמת המשתמשים. אסור לאפליקציות לשמור הקצאות של מפות סיביות כבדות ברקע כשעוברים למצבים האלה. השירותים האלה מיועדים למשימות שפועלות לאורך זמן, ולכן שמירה של נכסים גדולים פוגעת בחוויית המשתמש הכוללת ומאלצת את Low Memory Killer Daemon (LMKD) לפנות זיכרון על ידי סיום תהליכים עם עדיפות נמוכה יותר.
- רקע: האפליקציה מפעילה שירות הפועל ברקע, או שהועברה לאחרונה לרקע, אבל עדיין לא נשמרה במטמון. מצב התהליך הזה פחות חשוב מתהליכים שפועלים בחזית או תהליכים מורגשים, ולכן אפליקציות צריכות לשחרר כאן באופן מפורש נכסי מפת סיביות גדולים כדי להפחית את העומס על הזיכרון.
- במטמון: האפליקציה נמצאת במצב מטמון. המצב הזה רגיש מאוד לעומס על זיכרון המערכת, כמו LMK. כדי למנוע את הסרת האפליקציה על ידי מערכת ההפעלה, האפליקציות צריכות לצמצם באופן יזום את השימוש בזיכרון של מפת הסיביות במצב הזה.
גורמים לשימוש גבוה בזיכרון של מפת הסיביות
יכול להיות שגם זיכרון וירטואלי שלא נעשה בו שימוש ייכלל בחישוב. אם אתם רואים שימוש גבוה באופן לא צפוי בזיכרון של מפת הסיביות (bitmap), ודאו שאתם לא מקצים זיכרון שלא נעשה בו שימוש.
משאבים
ניתוח מפות ביט ב-Android Studio
פרופיל של מפות סיביות ב-Android Studio
אפשר להשתמש בכלי Memory Profiler כדי לבדוק הקצאות זיכרון בזמן אמת, ללכוד תמונות מצב של ה-heap ולנתח אובייקטים כדי לזהות דליפות זיכרון. בנוסף, אפשר להשתמש בכלי Heap Analyzer כדי לזהות דליפות זיכרון, לזהות הקצאות כפולות של מפות סיביות ולהציג חזותית את השמירה של אובייקטים.
זיהוי אוטומטי של דליפות זיכרון באמצעות LeakCanary
אפשר לשלב את ספריית LeakCanary כדי לאתר באופן אוטומטי דליפות זיכרון באפליקציה. LeakCanary מספקת ניתוח אוטומטי של ה-heap, ומזהה אובייקטים שהיו אמורים לעבור איסוף אשפה אבל עדיין מאוחסנים בזיכרון, כמו מפות סיביות שנשמרו על ידי רכיבים שהושמדו.
מסמכי תיעוד בנושא ביצועים של מפת סיביות (bitmap)
במקורות המידע האלה מפורטות שיטות מומלצות לטיפול יעיל במפות סיביות ברכיבים שונים של Android.
רשימת משימות למפתחים לביצוע אופטימיזציה של השימוש בזיכרון של מפת הסיביות (bitmap)
כדי לבצע אופטימיזציה של יעילות הזיכרון של מפת סיביות (bitmap), צריך לפעול לפי שלושת העקרונות המרכזיים: צמצום, שימוש חוזר ומיחזור.
- הקטנה: מזעור של הזיכרון שבשימוש הראשוני בזמן טעינה או הצגה של מפות סיביות.
- שימוש חוזר: הטמיעו מנגנוני שמירה במטמון כדי להימנע מהקצאות מיותרות של מפות סיביות.
- מיחזור: שחרור משאבים באופן יזום כדי לאפשר הקצאה מחדש של זיכרון לתהליכים פעילים.
רשימת המשימות הבאה למפתחים יכולה לעזור לכם לבצע אופטימיזציה של השימוש בזיכרון של מפת סיביות.
| עקרון מרכזי | אזור | תיאור |
|---|---|---|
| הפחתה | הסרת מפות סיביות כפולות | כדי לזהות הקצאות מיותרות של מפות סיביות, אפשר לנתח תמונות מצב של הזיכרון באמצעות הכלי Memory Profiler. אפשר לעיין במדריך בנושא ניהול הזיכרון של מפת הסיביות. |
| שימוש בספריות לטעינת תמונות | מומלץ להשתמש בספריות כמו Glide ו-Coil כדי להפוך את יצירת השרשורים, השמירה במטמון והפענוח היעיל לאוטומטיים. | |
| הטמעה של דגימה מצומצמת | פענוח תמונות כדי להתאים למידות של מאגר רכיבי ממשק המשתמש במקום לטעון נכסים ברזולוציה מלאה. | |
| שימוש ב-RGB_565 לתמונות אטומות | אפשר להקטין את הזיכרון שבשימוש ב-50% על ידי מעבר מ-ARGB_8888 להגדרה של 16 ביט לתמונות ללא שקיפות. |
|
| עדיפות ל-VectorDrawables | מומלץ להשתמש בוקטורים לסמלים ולגרפיקה בסיסית כדי להבטיח שינוי גודל חד עם תקורה מינימלית של זיכרון. | |
| אופטימיזציה של שליחת תמונות מצד השרת | הגדרת ממשקי API של קצה עורפי כדי להציג תמונות מותאמות לצפיפות של המכשיר ולמידות של מאגרי ממשק המשתמש. | |
| הסרת שוליים שקופים | כדי להימנע מהקצאת זיכרון לפיקסלים 'בלתי נראים', כדאי להשתמש ב-InsetDrawable או במרווחים פנימיים של פריסת רכיבים במקום במרווחים קבועים. מידע נוסף זמין במאמר פיתוח אפליקציות ל-Android עם ביצועים טובים של זיכרון. | |
| שימוש חוזר | הגדרת גדלי מטמון אופטימליים | התאמה של מגבלות הזיכרון והמטמון בדיסק בהתאם לזיכרון ה-RAM ולרזולוציית המסך של המכשיר. אפשר להיעזר במאמר בנושא שמירה במטמון של מפות סיביות. |
| מיחזור | מחיקת משאבים ברקע | הטמעה של TRIM_MEMORY_BACKGROUND כדי לנקות מטמונים ולשפר את היכולת של התהליך לשרוד במהלך לחץ על זיכרון המערכת. |
| הסרת נכסים כשהממשק מוסתר | משתמשים ב-TRIM_MEMORY_UI_HIDDEN כדי לשחרר מטמונים של מפות סיביות כשהאפליקציה לא גלויה יותר למשתמש. |
|
| מעקב אחרי דליפות זיכרון | אפשר להשתמש ב-LeakCanary וב-Memory Profiler כדי למצוא מפות סיביות שנשמרו אחרי שהרכיב LifecycleOwner נהרס. מידע נוסף מפורט במאמר בנושא ניהול הזיכרון של האפליקציה. |