בדף הזה מתוארים השיפורים השונים בניהול הזיכרון שהוצגו ב-Android 12.
נתונים סטטיסטיים של DMA-BUF ב-sysfs
ב-Android 11 וב-Android 12, אי אפשר לטעון את debugfs בגרסאות build של משתמשים. לכן, נתונים סטטיסטיים של 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 בבייטים. |
libdmabufinfo API מנתח את נתוני הסטטיסטיקה של DMA-BUF sysfs כדי להציג נתונים סטטיסטיים לכל כלי ייצוא ולכל מאגר.
חשוב לציין שמנהלי התקנים של ליבת מערכת שמייצאים DMA-BUF צריכים להגדיר את השדה exp_name של struct dma_buf_export_info בצורה נכונה לשם של הייצואן לפני שמפעילים את dma_buf_export() API כדי ליצור DMA-BUF.
ההרשאה הזו נדרשת כדי ש-libdmabufinfo וכלי dmabuf_dump יוכלו להפיק נתונים סטטיסטיים לכל תהליך ייצוא, שיוצגו בדוח באגים.
הכלי dmabuf_dump
עבר שינוי כדי להציג את המידע הזה באמצעות ארגומנט חדש, -b.
סטטיסטיקה של מסגרת ה-DMA-BUF heaps
התמיכה ב-ION ב-GKI 2.0 יוצאת משימוש לטובת מסגרת הערימות של DMA-BUF, שהיא חלק מליבת Linux במעלה הזרם.
הנתונים הסטטיסטיים הגלובליים הבאים של ION נמדדים ב-Android 11:
- הגודל הכולל של DMA-BUFs שמיוצאים על ידי כל ION heap
- הגודל הכולל של זיכרון שהוקצה מראש ולא נעשה בו שימוש, שמאוחסן על ידי כל ערימת 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() עם
PID0עבורMemtrackTypeשאינוGLלא יכולה להיכשל. במקום זאת, הפונקציה צריכה להחזיר 0. - הפתרון GPU memory tracepoint/eBPF שנוסף ב-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 שנמצא בשימוש.
כך אפשר לקבל נתונים מדויקים יותר על הזיכרון ולראות את השימוש בזיכרון של ה-GPU ובמאגר ה-DMA. כדי לשפר את הדיווח על זיכרון 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, ולהטמיע את ה-API של AIDL memtrack HAL getMemory() כדי להחזיר בצורה נכונה את הזיכרון הפרטי הכולל של ה-GPU כשמבצעים קריאה עם PID 0 ל-MemtrackType::GL ול-MemtrackRecord::FLAG_SMAPS_UNACCOUNTED.