בדף הזה מתוארות השיפורים השונים בדיווח על שימוש בזיכרון שנוספו ב-Android 12.
נתונים סטטיסטיים של DMA-BUF ב-sysfs
ב-Android 11 וב-Android 12 אי אפשר לטעון את debugfs
ב-builds של משתמשים. אז הנתונים הסטטיסטיים של DMA-BUF נוספו ל-sysfs
בספרייה /sys/kernel/dmabuf/buffers
ב-Android 12.
נתיב | תיאור |
---|---|
/sys/kernel/dmabuf/buffers
|
הספרייה /sys/kernel/dmabuf/buffers מכילה תמונת מצב של המצב הפנימי של כל 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
.
נתונים סטטיסטיים לגבי מסגרת ה-heaps של DMA-BUF
ION ב-GKI 2.0 הוצא משימוש והוחלף במסגרת של DMA-BUF heaps, שמהווה חלק מליבת Linux במקור.
ב-Android 11 מתבצע מעקב אחרי הנתונים הסטטיסטיים הגלובליים הבאים של ION:
- הגודל הכולל של DMA-BUF שיוצאו מכל ערימה של ION
- הגודל הכולל של הזיכרון שהוקצה מראש ולא נמצא בשימוש, שנשמר בכל ערימה של ION
אין ממשק זמין לחשוף נתונים סטטיסטיים של תמונת מצב של הזיכרון לכל ION ב-Android 11.
בטבלה הבאה מוצגת השוואה בין ממשקי הנתונים הסטטיסטיים של ION לבין הממשקים המקבילים במכשירים שמשתמשים במסגרת הערימה (heap framework) של DMA-BUF ב-Android 12.
Android 11 או מכשירים שהושקעו עם תמיכה ב-ION ב-Android 12 | מכשירי Android 12 שהושקעו עם אשכולות DMA-BUF | |
---|---|---|
נתונים סטטיסטיים של ION לכל אשכול | ללא | בוצע ניתוח מנתונים סטטיסטיים של sysfs DMA-BUF |
הגודל הכולל של DMA-BUFs שמיוצאים | /sys/kernel/ion/total_heap_size_kb
(לא כולל את גודל אזורי השוק הייעודיים (DMA-BUF) שיוצאו על ידי יצואנים שהם לא ION) |
ניתוח מנתוני sysfs של DMA-BUF
(כולל את הגודל של כל DMA-BUFs שיוצאו). |
סך כל הזיכרון שנאסף בערימה | /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-BUF ממופים לשטח הכתובות של GPU
לכן, ערכי DMA-BUF שמופו זיכרון לשטח הכתובות של ה-GPU ירדו פעמיים כשחושב נפח ה-RAM שאבד. ב-Android 12 מוטמעת פתרון לחישוב הגודל של DMA-BUFs שממופים למרחב הכתובות של ה-GPU, כלומר הוא נספר רק פעם אחת בחישוב של זיכרון RAM שאבד.
פרטי הפתרון הם:
- כשמתבצעת קריאה ל-Memtrack HAL API
getMemory()
, כשמתבצעת קריאה אליו באמצעות PID 0, צריך לדווח על סך הזיכרון הגלובלי של GPU-private, עבור MemtrackType::GL ו-MemtrackRecord::FLAG_SMAPS_UNACCOUNTED. - קריאה לפונקציה getMemory() עם
PID
0
עבורMemtrackType
שאינוGL
לא יכולה להיכשל. במקום זאת, הוא צריך להחזיר 0. - הפתרון GPU memory tracepoint/eBPF שנוסף ב-Android 12 מתייחס לזיכרון ה-GPU הכולל. מחסירים את הזיכרון הפרטי הכולל של ה-GPU מהזיכרון הכולל של ה-GPU, ומקבלים את הגודל של ה-DMA-BUFs שממופים למרחב הכתובות של ה-GPU. לאחר מכן ניתן להשתמש בערך כדי לשפר את הדיוק של חישובי RAM שאבדו על ידי התייחסות נכונה לשימוש בזיכרון של ה-GPU.
- זיכרון ה-GPU הפרטי נכלל ב-
totalPss
ברוב הטמעות ה-HAL של Memtrack, ולכן צריך לבטל את הכפילויות שלו לפני שמסירים אותו מ-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. הטמעת memtrack AIDL HAL לצורך ניהול יעיל יותר של זיכרון RAM שאבד. התכונה הזו לא תלויה בשירותי 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-private כאשר קוראים לו באמצעות PID 0 עבור MemtrackType::GL
ו-MemtrackRecord::FLAG_SMAPS_UNACCOUNTED.