הטמע ניהול זיכרון DMABUF ו-GPU באנדרואיד 12

דף זה מתאר את שיפורי חשבונאות הזיכרון השונים שהוצגו באנדרואיד 12.

סטטיסטיקות DMA-BUF ב-sysfs

ב-Android 11 ו-Android 12, לא ניתן להרכיב debugfs ב-User builds. אז סטטיסטיקות DMA-BUF נוספו ל- sysfs בספריית /sys/kernel/dmabuf/buffers באנדרואיד 12.

נָתִיב תיאור
/sys/kernel/dmabuf/buffers הספרייה /sys/kernel/dmabuf/buffers מכילה תמונת מצב של המצב הפנימי של כל DMA-BUF. /sys/kernel/dmabuf/buffers/<inode_number> מכיל את הנתונים הסטטיסטיים עבור ה-DMA-BUF עם מספר האינוד הייחודי <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-BUFs חייבים להגדיר את שדה exp_name של struct dma_buf_export_info בצורה נכונה לשם היצואן לפני הפעלת ה-API dma_buf_export() כדי ליצור DMA-BUF. זה נדרש עבור libdmabufinfo והכלי dmabuf_dump כדי להפיק נתונים סטטיסטיים לכל יצואן אשר נחשפים לאחר מכן ב-bugreport.

הכלי dmabuf_dump שונה כדי להוציא מידע זה עם ארגומנט חדש, -b .

נתונים סטטיסטיים עבור מסגרת ה-DMA-BUF heaps

ION ב-GKI 2.0 מובטל לטובת מסגרת ה-DMA-BUF heaps , שהיא חלק מקרנל הלינוקס במעלה הזרם.

הנתונים הסטטיסטיים הגלובליים של ION עוקבים באנדרואיד 11:

  • גודל כולל של DMA-BUFs המיוצאים על ידי כל ערימת ION
  • גודל כולל של זיכרון שהוקצה מראש שאינו בשימוש המאוחסן על ידי כל ערימת ION

אין ממשק זמין לחשיפת סטטיסטיקות פר-ION באנדרואיד 11.

הטבלה הבאה משווה את ממשקי הנתונים הסטטיסטיים של ION עם מקביליהם עבור מכשירים המשתמשים במסגרת ה-DMA-BUF heap ב-Android 12.

אנדרואיד 11 או מכשירים מושקים עם תמיכה ב-ION באנדרואיד 12 מכשירים מושקים עם ערימות DMA-BUF באנדרואיד 12
סטטיסטיקות ION לכל ערמה אף אחד מנותח מסטטיסטיקות DMA-BUF sysfs
גודל כולל של DMA-BUFs שיוצאו /sys/kernel/ion/total_heap_size_kb
(לא כולל את הגודל של DMA-BUFs המיוצאים על ידי יצואנים שאינם ION)
מנותח מסטטיסטיקות DMA-BUF sysfs
(כולל את הגודל של כל DMA-BUFs שיוצאו).
זיכרון כולל מאוחד בערימות /sys/kernel/ion/total_pool_size_kb /sys/kernel/dma_heap/total_pool_size_kb

שפר את דיוק חישוב ה-RAM שאבד

בעבר חישוב ה-RAM האבוד נעשה באופן הבא:

final long lostRAM = memInfo.getTotalSizeKb( ) - ( totalPss - totalSwapPss )

- memInfo.getFreeSizeKb() - memInfo.getCachedSizeKb()

- kernelUsed - memInfo.getZramTotalSizeKb() ;

רכיב totalPss כלל את השימוש בזיכרון GPU (מוחזר על ידי ממשק getMemory() של Memtrack HAL). רכיב kernelUsed כלל את השימוש הכולל בזיכרון DMA-BUF. עם זאת, עבור מכשירי אנדרואיד, זיכרון ה-GPU הגיע מהדברים הבאים:

  • הקצאות ישירות שנעשו על ידי מנהל התקן ה-GPU באמצעות מקצה עמודים פיזי
  • DMA-BUFs ממופים למרחב הכתובות של GPU

לכן, DMA-BUFs שמופו בזיכרון למרחב הכתובות של ה-GPU הופחתו פעמיים כאשר חושב זיכרון RAM שאבד. אנדרואיד 12 מיישמת פתרון לחישוב הגודל של DMA-BUFs הממופים במרחב הכתובות של ה-GPU, מה שאומר שהוא נלקח בחשבון רק פעם אחת בחישוב זיכרון 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 אוכפות את הכלל לפיו מכשירים המופעלים באנדרואיד 12 עם גרסת ליבת לינוקס 5.4 ומעלה תומכים ב- getGpuDeviceInfo() API.

Memtrack HAL API חדש getGpuDeviceInfo() חייב להחזיר מידע על מכשיר ה-GPU שנמצא בשימוש.

זה מספק חשבונאות זיכרון טובה יותר ונראות לתוך חיץ DMA ושימוש בזיכרון GPU. יישם את memtrack AIDL HAL לניהול טוב יותר של זיכרון RAM וזיכרון שאבדו. תכונה זו אינה תלויה בשירותי Google.

יישום

תכונה זו תלויה ב- AIDL Memtrack HAL , והנחיות להטמעתה באנדרואיד 12 כלולים בקוד כהערות.

כל ה-HIDL HALs מתוכננים להיות מומרים ל-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.