Auf dieser Seite werden die verschiedenen Verbesserungen bei der Speicherverwaltung beschrieben, die in Android 12 eingeführt wurden.
DMA-BUF-Statistiken in sysfs
Unter Android 11 und Android 12 kann debugfs
nicht in Nutzerbuilds bereitgestellt werden. Daher wurden DMA-BUF-Statistiken in Android 12 dem Dateinamen sysfs
im Verzeichnis /sys/kernel/dmabuf/buffers
hinzugefügt.
Pfad | Beschreibung |
---|---|
/sys/kernel/dmabuf/buffers
|
Das Verzeichnis /sys/kernel/dmabuf/buffers enthält einen Snapshot des internen Status jedes DMA-BUF.
/sys/kernel/dmabuf/buffers/<inode_number> enthält die Statistiken für den DMA-BUF mit der eindeutigen Inode-Nummer <inode_number> .
|
/sys/kernel/dmabuf/buffers/<inode_number>/exporter_name
|
Diese schreibgeschützte Datei enthält den Namen des DMA-BUF-Exporteurs. |
/sys/kernel/dmabuf/buffers/<inode_number>/size
|
In dieser schreibgeschützten Datei wird die Größe des DMA-BUF in Byte angegeben. |
Die libdmabufinfo
API analysiert die DMA-BUF-sysfs
-Statistiken, um Statistiken pro Exporteur und pro Puffer bereitzustellen.
Kerneltreiber, die DMA-BUFs exportieren, müssen das exp_name
-Feld von struct dma_buf_export_info
korrekt auf den Namen des Exporteurs festlegen, bevor sie die dma_buf_export()
API aufrufen, um einen DMA-BUF zu erstellen.
Dies ist erforderlich, damit libdmabufinfo
und das dmabuf_dump
-Tool Statistiken pro Exporteur ableiten können, die dann im Fehlerbericht angezeigt werden.
Das Tool dmabuf_dump wurde so geändert, dass diese Informationen mit einem neuen Argument, -b
, ausgegeben werden.
Statistiken für das DMA-BUF-Heaps-Framework
ION in GKI 2.0 wird zugunsten des DMA-BUF-Heaps-Frameworks eingestellt, das Teil des Upstream-Linux-Kernels ist.
In Android 11 werden die folgenden globalen ION-Statistiken erfasst:
- Gesamtgröße der DMA-BUFs, die von jedem ION-Heap exportiert wurden
- Gesamtgröße des nicht verwendeten vorab zugewiesenen Arbeitsspeichers, der von jedem ION-Heap gespeichert wird
In Android 11 gibt es keine Benutzeroberfläche, über die Statistiken pro ION-Heap verfügbar gemacht werden können.
In der folgenden Tabelle werden die ION-Statistikschnittstellen mit ihren Gegenstücken für Geräte verglichen, die das DMA-BUF-Heap-Framework in Android 12 verwenden.
Android 11 oder Geräte, die bei Markteinführung Android 12 mit ION-Unterstützung nutzen | Geräte, die bei Markteinführung Android 12 mit DMA-BUF-Haufen ausgeliefert werden | |
---|---|---|
ION-Statistiken pro Heap | Keine | Aus DMA-BUF-sysfs-Statistiken geparst |
Gesamtgröße der exportierten DMA-BUFs | /sys/kernel/ion/total_heap_size_kb
(Die Größe von DMA-BUFs, die von anderen Exportern als ION exportiert werden, ist nicht enthalten.) |
Aus den sysfs-Statistiken von DMA-BUFs geparst
(enthält die Größe aller exportierten DMA-BUFs). |
Gesamter Arbeitsspeicher, der von Heaps verwaltet wird | /sys/kernel/ion/total_pool_size_kb |
/sys/kernel/dma_heap/total_pool_size_kb |
Genauigkeit der Berechnung des verlorenen Arbeitsspeichers verbessern
Bisher wurde der verlorene RAM so berechnet:
final long lostRAM
= memInfo.getTotalSizeKb(
) – (totalPss
– totalSwapPss
)
– memInfo.getFreeSizeKb()
– memInfo.getCachedSizeKb()
– kernelUsed
– memInfo.getZramTotalSizeKb()
;
Die Komponente totalPss
enthielt die GPU-Arbeitsspeichernutzung, die von der getMemory()-Schnittstelle der Memtrack HAL zurückgegeben wurde. Die Komponente kernelUsed
enthielt die Gesamtnutzung des DMA-BUF-Speichers.
Bei Android-Geräten stammte der GPU-Speicher jedoch aus folgenden Quellen:
- Direkte Zuordnungen, die vom GPU-Treiber mithilfe des physischen Seitenzuweisers vorgenommen werden
- DMA-BUFs, die dem GPU-Adressraum zugeordnet sind
Daher wurden DMA-BUFs, die im GPU-Adressraum arbeitsspeicherzugeordnet waren, bei der Berechnung des verlorenen RAM doppelt abgezogen. In Android 12 wird eine Lösung implementiert, um die Größe von DMA-BUFs zu berechnen, die in den GPU-Adressraum zugeordnet sind. Das bedeutet, dass sie nur einmal bei der Berechnung des verlorenen RAM berücksichtigt wird.
Die Details der Lösung sind:
- Wenn die Memtrack HAL API
getMemory()
mit PID 0 aufgerufen wird, muss sie den gesamten globalen GPU-privaten Arbeitsspeicher für MemtrackType::GL und MemtrackRecord::FLAG_SMAPS_UNACCOUNTED angeben. - Der Aufruf von „getMemory()“ mit „
PID
0
“ für eine andereMemtrackType
alsGL
darf nicht fehlschlagen. Stattdessen muss 0 zurückgegeben werden. - Die in Android 12 hinzugefügte Lösung GPU-Arbeitsspeicher-Tracepoint/eBPF berücksichtigt den gesamten GPU-Arbeitsspeicher. Wenn Sie den gesamten privaten GPU-Arbeitsspeicher vom gesamten GPU-Arbeitsspeicher abziehen, erhalten Sie die Größe der DMA-BUFs, die in den GPU-Adressraum zugeordnet sind. Mit diesem Wert lässt sich die Genauigkeit der Berechnungen für verlorenen RAM verbessern, da die GPU-Arbeitsspeichernutzung korrekt berücksichtigt wird.
- Der private GPU-Speicher ist in den meisten Memtrack HAL-Implementierungen in
totalPss
enthalten und muss daher dedupliziert werden, bevor er auslostRAM
entfernt wird.
Die implementierte Lösung wird im nächsten Abschnitt beschrieben.
Memtrack-Variabilität aus verlorenem RAM entfernen
Da die Memtrack HAL-Implementierungen je nach Partner variieren können, ist der GPU-Speicher, der in totalPSS
aus der HAL enthalten ist, nicht immer konsistent. Um die Variabilität aus lostRAM
zu entfernen, wird der in MemtrackType::GRAPHICS
und MemtrackType::GL
berücksichtigte Arbeitsspeicher während der Berechnung von lostRAM
aus totalPss
entfernt.
Der MemtrackType::GRAPHICS
-Speicher wird aus totalPss
entfernt und durch den totalExportedDmabuf
-Speicher in der lostRAM
-Berechnung in ActivityManagerService.java ersetzt, wie unten dargestellt:
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;
Der MemtrackType::GL
-Arbeitsspeicher wird aus totalPss
entfernt und durch den privaten GPU-Arbeitsspeicher (gpuPrivateUsage
) in der lostRAM
-Berechnung in ActivityManagerService.java ersetzt, wie unten dargestellt:
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;
Aktualisierte Berechnung des verlorenen Arbeitsspeichers
Sowohl der gesamte private GPU-Arbeitsspeicher als auch der gesamte exportierte DMA-Pufferspeicher sind in kernelUsed + totalPss
enthalten, der von lostRAM
entfernt wird. Dadurch werden sowohl Doppelzählungen als auch die Memtrack-Variabilität bei der Berechnung des verlorenen RAM eliminiert.
final long lostRAM = memInfo.getTotalSizeKb() - (totalPss - totalSwapPss)
- memInfo.getFreeSizeKb() - memInfo.getCachedSizeKb()
- kernelUsed - memInfo.getZramTotalSizeKb();
Zertifizierungsstufe
Bei VTS-Tests wird die Regel erzwungen, dass Geräte, die mit Android 12 und der Linux-Kernel-Version 5.4 oder höher gestartet werden, die API getGpuDeviceInfo() unterstützen.
Eine neue Memtrack HAL API getGpuDeviceInfo()
muss Informationen zum verwendeten GPU-Gerät zurückgeben.
Dies ermöglicht eine bessere Speichererfassung und Transparenz bei der DMA-Puffer- und GPU-Speichernutzung. Implementieren Sie die memtrack-AIDL-HAL für eine bessere Erfassung von verlorenem RAM und Speicher. Diese Funktion ist unabhängig von Google-Diensten.
Implementierung
Diese Funktion hängt von der AIDL Memtrack HAL ab. Eine Anleitung zur Implementierung in Android 12 ist im Code als Kommentar enthalten.
Alle HIDL HALs sollen in zukünftigen Releases in AIDL konvertiert werden.
Die folgenden APIs wurden zu core/java/android/os/Debug.java
hinzugefügt:
/**
* 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();
Damit Ihre Version wie vorgesehen funktioniert, müssen Sie die Tracepoints in Ihre GPU-Treiber einbinden und die AIDL memtrack HAL getMemory()
API implementieren, damit der globale private GPU-Speicher korrekt zurückgegeben wird, wenn MemtrackType::GL und MemtrackRecord::FLAG_SMAPS_UNACCOUNTED mit PID 0 aufgerufen werden.