בדף הזה מתוארים השיפורים השונים בניהול הזיכרון שהוצגו ב-Android 12.
נתונים סטטיסטיים של DMA-BUF ב-sysfs
ב-Android 11 וב-Android 12, אי אפשר לטעון את debugfs ב-User builds. לכן, נתונים סטטיסטיים של DMA-BUF נוספו ל-sysfs בספרייה /sys/kernel/dmabuf/buffers ב-Android 12.
| נתיב | תיאור |
|---|---|
/sys/kernel/dmabuf/buffers
|
הספרייה /sys/kernel/dmabuf/buffers מכילה קובץ snapshot של המצב הפנימי של כל DMA-BUF.
/sys/kernel/dmabuf/buffers/<inode_number> מכיל את הסטטיסטיקה של DMA-BUF עם מספר ה-inode הייחודי <inode_number>.
|
/sys/kernel/dmabuf/buffers/<inode_number>/exporter_name
|
הקובץ הזה לקריאה בלבד מכיל את השם של רכיב הייצוא DMA-BUF. |
/sys/kernel/dmabuf/buffers/<inode_number>/size
|
הקובץ הזה לקריאה בלבד מציין את הגודל של DMA-BUF בבייטים. |
ממשק ה-API libdmabufinfo מנתח את הנתונים הסטטיסטיים של DMA-BUF sysfs כדי להציג נתונים סטטיסטיים לכל יצואן ולכל מאגר.
מנהלי התקנים של ליבת מערכת שמייצאים DMA-BUF צריכים להגדיר את השדה exp_name של struct dma_buf_export_info בצורה נכונה לשם הייצוא לפני שמפעילים את API dma_buf_export() כדי ליצור DMA-BUF. הפעולה הזו נדרשת כדי ש-libdmabufinfo וכלי dmabuf_dump יוכלו להפיק נתונים סטטיסטיים לכל כלי ייצוא, שיוצגו בדוח באגים.
הכלי dmabuf_dump שונה כך שהוא מוציא את המידע הזה עם ארגומנט חדש, -b.
סטטיסטיקות של מסגרת ה-DMA-BUF heaps
התמיכה ב-ION ב-GKI 2.0 יוצאת משימוש לטובת מסגרת הערימות של DMA-BUF, שהיא חלק מליבת לינוקס במעלה הזרם.
הנתונים הסטטיסטיים הגלובליים הבאים של ION נמדדים ב-Android 11:
- הגודל הכולל של DMA-BUFs שמיוצאים על ידי כל ערימת ION
- הגודל הכולל של זיכרון שהוקצה מראש ולא נעשה בו שימוש, שמאוחסן על ידי כל ערימת ION
אין ממשק שמאפשר לחשוף נתונים סטטיסטיים של ערימה לכל ION ב-Android 11.
בטבלה הבאה מוצגת השוואה בין ממשקי הנתונים הסטטיסטיים של ION לבין המקבילים שלהם במכשירים שמשתמשים במסגרת הערימה DMA-BUF ב-Android 12.
| Android 11 או מכשירים שמופעלת בהם תמיכה ב-ION ב-Android 12 | מכשירים שמופעלים עם ערימות DMA-BUF ב-Android 12 | |
|---|---|---|
| נתונים סטטיסטיים של ION לכל ערימה | ללא | מנותח מתוך נתונים סטטיסטיים של DMA-BUF sysfs |
| הגודל הכולל של קובצי DMA-BUF שיוצאו | /sys/kernel/ion/total_heap_size_kb
(Doesn’t include the size of DMA-BUFs exported by non-ION exporters) |
הניתוח מתבצע מנתוני הסטטיסטיקה של DMA-BUF sysfs
(כולל הגודל של כל DMA-BUF שיוצא). |
| סך הזיכרון שמוקצה לערימות | /sys/kernel/ion/total_pool_size_kb |
/sys/kernel/dma_heap/total_pool_size_kb |
שיפור הדיוק של חישוב ה-RAM שאבד
בעבר, חישוב ה-RAM שאבד בוצע באופן הבא:
נתון סופי ארוך lostRAM = memInfo.getTotalSizeKb() - (totalPss - totalSwapPss)
- memInfo.getFreeSizeKb() - memInfo.getCachedSizeKb()
- kernelUsed – memInfo.getZramTotalSizeKb().
הרכיב totalPss כלל את השימוש בזיכרון ה-GPU (שהוחזר על ידי הממשק getMemory() של Memtrack HAL). הרכיב kernelUsed כלל את השימוש הכולל בזיכרון DMA-BUF.
עם זאת, במכשירי Android, זיכרון ה-GPU מגיע מהמקורות הבאים:
- הקצאות ישירות שמתבצעות על ידי הדרייבר של ה-GPU באמצעות מקצה דפים פיזי
- מיפוי של DMA-BUFs למרחב הכתובות של ה-GPU
לכן, כשחישבנו את זיכרון ה-RAM שאבד, הפחתנו פעמיים את ה-DMA-BUFs שמופו לזיכרון במרחב הכתובות של ה-GPU. ב-Android 12, מוטמע פתרון לחישוב הגודל של DMA-BUFs שממופים למרחב הכתובות של ה-GPU. המשמעות היא שהם נספרים רק פעם אחת בחישוב של Lost RAM.
הפרטים של הפתרון הם:
- כשמפעילים את Memtrack HAL API
getMemory()עם PID 0, הוא צריך לדווח על הזיכרון הפרטי הכולל של ה-GPU, עבורMemtrackType::GLו-MemtrackRecord::FLAG_SMAPS_UNACCOUNTED. -
getMemory()כשמפעילים אותה עםPID 0עבורMemtrackTypeשאינוGLלא יכולה להיכשל. במקום זאת, הפונקציה צריכה להחזיר 0. - פתרון נקודת המעקב/eBPF של זיכרון ה-GPU שנוסף ב-Android 12 מתייחס לזיכרון ה-GPU הכולל. ההפרש בין זיכרון ה-GPU הכולל לבין זיכרון ה-GPU הפרטי הכולל הוא הגודל של DMA-BUFs שמופה למרחב הכתובות של ה-GPU. אפשר להשתמש בערך הזה כדי לשפר את הדיוק של חישובי ה-RAM שאבד, על ידי התחשבות נכונה בשימוש בזיכרון ה-GPU.
- זיכרון ה-GPU הפרטי נכלל ב-
totalPssברוב ההטמעות של Memtrack HAL, ולכן צריך לבטל את הכפילות שלו לפני שמסירים אותו מ-lostRAM.
הפתרון שהוטמע מפורט בקטע הבא.
הסרת השונות של Memtrack מזיכרון RAM שאבד
ההטמעות של Memtrack HAL עשויות להיות שונות בין שותפים, ולכן זיכרון ה-GPU שכלול ב-totalPSS מ-HAL לא תמיד עקבי. כדי להסיר את השונות מ-lostRAM, הזיכרון שנלקח בחשבון ב-MemtrackType::GRAPHICS וב-MemtrackType::GL מוסר מ-totalPss במהלך החישוב של lostRAM.
הזיכרון של MemtrackType::GRAPHICS מוסר מ-totalPss ומוחלף בזיכרון של totalExportedDmabuf בחישוב של lostRAM ב-ActivityManagerService.java, כמו שמוצג בקוד הבא:
final long totalExportedDmabuf = Debug.getDmabufTotalExportedKb();
. . .
final long dmabufUnmapped = totalExportedDmabuf - dmabufMapped;
. . .
// Account unmapped dmabufs as part of the kernel memory allocations
kernelUsed += dmabufUnmapped;
// Replace Memtrack HAL reported Graphics category with mapped dmabufs
totalPss -= totalMemtrackGraphics;
totalPss += dmabufMapped;
הזיכרון של MemtrackType::GL מוסר מ-totalPss ומוחלף בזיכרון הפרטי של ה-GPU (gpuPrivateUsage) בחישוב של lostRAM ב-ActivityManagerService.java, כמו שמוצג בקוד הבא:
final long gpuUsage = Debug.getGpuTotalUsageKb();
. . .
final long gpuPrivateUsage = Debug.getGpuPrivateMemoryKb();
. . .
// Replace the Memtrack HAL-reported GL category with private GPU allocations.
// Count it as part of the kernel memory allocations.
totalPss -= totalMemtrackGl;
kernelUsed += gpuPrivateUsage;
עדכון של חישוב ה-RAM שאבד
הזיכרון הכולל הפרטי של ה-GPU והזיכרון הכולל של מאגר ה-DMA המיוצא כלולים ב-kernelUsed + totalPss שמוסר מ-lostRAM. כך נמנעת ספירה כפולה ומשתנות של Memtrack בחישוב של זיכרון RAM שאבד.
final long lostRAM = memInfo.getTotalSizeKb() - (totalPss - totalSwapPss)
- memInfo.getFreeSizeKb() - memInfo.getCachedSizeKb()
- kernelUsed - memInfo.getZramTotalSizeKb();
אימות
במסגרת בדיקות VTS נאכף הכלל שלפיו מכשירים שמופעלים ב-Android 12 עם ליבת Linux בגרסה 5.4 ואילך תומכים ב-API getGpuDeviceInfo().
Memtrack HAL API חדש getGpuDeviceInfo() צריך להחזיר מידע על מכשיר ה-GPU שנמצא בשימוש.
כך מתקבלת ראייה טובה יותר של השימוש בזיכרון ושל מאגר ה-DMA וזיכרון ה-GPU. כדי לשפר את הדיווח על זיכרון RAM וזיכרון שאבדו, כדאי להטמיע את memtrack AIDL HAL. התכונה הזו לא תלויה בשירותי Google.
הטמעה
התכונה הזו תלויה ב-AIDL Memtrack HAL, והוראות להטמעה שלה ב-Android 12 כלולות בקוד כהערות. מתוכנן שכל מודולי ה-HAL של HIDL יומרו ל-AIDL בגרסאות עתידיות.
ממשקי ה-API הבאים נוספו ל-core/java/android/os/Debug.java:
/**
* Return total memory size in kilobytes for exported DMA-BUFs or -1 if
* the DMA-BUF sysfs stats at /sys/kernel/dmabuf/buffers could not be read.
*
* @hide
*/
public static native long getDmabufTotalExportedKb();
/**
* Return memory size in kilobytes allocated for DMA-BUF heap pools or -1 if
* /sys/kernel/dma_heap/total_pools_kb could not be read.
*
* @hide
*/
public static native long getDmabufHeapPoolsSizeKb();
כדי לוודא שהגרסה שלכם פועלת כמצופה, צריך לשלב את נקודות המעקב במנהלי ההתקנים של ה-GPU, ולהטמיע את AIDL memtrack HAL getMemory() API כדי להחזיר בצורה נכונה את הזיכרון הפרטי הכולל של ה-GPU כשמתבצעת קריאה עם PID 0 עבור MemtrackType::GL ו-MemtrackRecord::FLAG_SMAPS_UNACCOUNTED.