Auf dieser Seite werden die verschiedenen Verbesserungen bei der Speicherabrechnung beschrieben, die in Android 12 eingeführt wurden.
DMA-BUF-Statistiken in sysfs
In Android 11 und Android 12 können debugfs
nicht in Benutzer-Builds gemountet werden. Daher wurden DMA-BUF-Statistiken zu sysfs
im Verzeichnis /sys/kernel/dmabuf/buffers
in Android 12 hinzugefügt.
Weg | Beschreibung |
---|---|
/sys/kernel/dmabuf/buffers | Das Verzeichnis /sys/kernel/dmabuf/buffers enthält eine Momentaufnahme 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-Exporters. |
/sys/kernel/dmabuf/buffers/<inode_number>/size | Diese schreibgeschützte Datei gibt die Größe des DMA-BUF in Bytes an. |
Die libdmabufinfo
-API analysiert die DMA-BUF- sysfs
-Statistiken, um Statistiken pro Exporter und pro Puffer anzuzeigen.
Bitte beachten Sie, dass Kerneltreiber, die DMA-BUFs exportieren, das exp_name
Feld der struct dma_buf_export_info
korrekt auf den Namen des Exporteurs setzen müssen, bevor sie die API dma_buf_export()
aufrufen, um einen DMA-BUF zu erstellen. Dies ist für libdmabufinfo
und das dmabuf_dump
Tool erforderlich, um Statistiken pro Exporter abzuleiten, die dann im Fehlerbericht angezeigt werden.
Das dmabuf_dump- Tool wurde geändert, um diese Informationen mit einem neuen Argument, -b
auszugeben.
Statistiken für das DMA-BUF-Heaps-Framework
ION in GKI 2.0 wird zugunsten des DMA-BUF-Heaps-Frameworks veraltet, das Teil des Upstream-Linux-Kernels ist.
Die folgenden globalen ION-Statistiken werden in Android 11 verfolgt:
- Gesamtgröße der von jedem ION-Heap exportierten DMA-BUFs
- Gesamtgröße des ungenutzten vorab zugewiesenen Speichers, der von jedem ION-Heap gespeichert wird
In Android 11 ist keine Schnittstelle zum Offenlegen von Heap-Statistiken pro ION verfügbar.
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 mit ION-Unterstützung in Android 12 starten | Geräte, die mit DMA-BUF-Heaps in Android 12 gestartet werden | |
---|---|---|
ION-Statistiken pro Heap | Keiner | Aus DMA-BUF-Sysfs-Statistiken analysiert |
Gesamtgröße der exportierten DMA-BUFs | /sys/kernel/ion/total_heap_size_kb (Beinhaltet nicht die Größe der DMA-BUFs, die von Nicht-ION-Exporteuren exportiert werden) | Aus DMA-BUF-Sysfs-Statistiken analysiert (beinhaltet die Größe aller exportierten DMA-BUFs). |
Gesamtspeicher, gepoolt durch Heaps | /sys/kernel/ion/total_pool_size_kb | /sys/kernel/dma_heap/total_pool_size_kb |
Verbessern Sie die Genauigkeit der Berechnung des verlorenen RAM
Zuvor wurde die Berechnung des verlorenen RAM wie folgt durchgeführt:
final long lostRAM
= memInfo.getTotalSizeKb(
) - ( totalPss
- totalSwapPss
)
- memInfo.getFreeSizeKb()
- memInfo.getCachedSizeKb()
- kernelUsed
- memInfo.getZramTotalSizeKb()
;
Die totalPss
Komponente enthielt die GPU-Speichernutzung (zurückgegeben von der getMemory()- Schnittstelle des Memtrack HAL). Die Komponente kernelUsed
enthielt die gesamte DMA-BUF-Speichernutzung. Bei Android-Geräten stammte der GPU-Speicher jedoch von Folgendem:
- Direkte Zuweisungen durch den GPU-Treiber mithilfe der physischen Seitenzuweisung
- DMA-BUFs werden dem GPU-Adressraum zugeordnet
Daher wurden DMA-BUFs, die dem GPU-Adressraum speicherzugeordnet waren, bei der Berechnung des RAM-Verlusts zweimal subtrahiert. Android 12 implementiert eine Lösung zur Berechnung der Größe von DMA-BUFs, die dem GPU-Adressraum zugeordnet sind, was bedeutet, dass sie bei der Berechnung des verlorenen RAM nur einmal berücksichtigt werden.
Die Details der Lösung lauten wie folgt:
- Wenn die Memtrack-HAL-API
getMemory()
mit PID 0 aufgerufen wird, muss sie den globalen gesamten privaten GPU-Speicher für MemtrackType::GL und MemtrackRecord::FLAG_SMAPS_UNACCOUNTED melden. - getMemory() darf beim Aufruf mit
PID
0
für einen anderenMemtrackType
alsGL
nicht fehlschlagen. Es muss stattdessen 0 zurückgeben. - Die in Android 12 hinzugefügte GPU-Speicher-Tracepoint/eBPF -Lösung berücksichtigt den gesamten GPU-Speicher. Durch Subtrahieren des gesamten privaten GPU-Speichers vom gesamten GPU-Speicher erhält man die Größe der DMA-BUFs, die dem GPU-Adressraum zugeordnet sind. Der Wert kann dann verwendet werden, um die Genauigkeit der Berechnungen des verlorenen RAM zu verbessern, indem die GPU-Speichernutzung 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 detailliert beschrieben.
Entfernen Sie die Memtrack-Variabilität durch verlorenen RAM
Da Memtrack-HAL-Implementierungen je nach Partner variieren können, ist der in totalPSS
aus dem HAL enthaltene GPU-Speicher nicht immer konsistent. Um die Variabilität von lostRAM
zu beseitigen, wird der in MemtrackType::GRAPHICS
und MemtrackType::GL
berücksichtigte Speicher während der lostRAM
Berechnung aus totalPss
entfernt.
MemtrackType::GRAPHICS
Speicher wird aus totalPss
entfernt und durch den totalExportedDmabuf
Speicher in der lostRAM
Berechnung in ActivityManagerService.java ersetzt, wie unten gezeigt:
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
Speicher wird aus totalPss
entfernt und durch den privaten GPU-Speicher ( gpuPrivateUsage
) in der lostRAM
Berechnung in ActivityManagerService.java ersetzt, wie unten gezeigt:
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;
Berechnung des verlorenen RAM aktualisiert
Sowohl der gesamte private GPU-Speicher als auch der gesamte exportierte DMA-Pufferspeicher sind in kernelUsed + totalPss
enthalten, das aus lostRAM
entfernt wird. Dies eliminiert sowohl Doppelzählungen als auch Memtrack-Variabilität durch die Berechnung des verlorenen RAM.
final long lostRAM = memInfo.getTotalSizeKb() - (totalPss - totalSwapPss)
- memInfo.getFreeSizeKb() - memInfo.getCachedSizeKb()
- kernelUsed - memInfo.getZramTotalSizeKb();
Validierung
VTS-Tests erzwingen die Regel, dass Geräte, die in Android 12 mit einer Linux-Kernelversion 5.4 oder höher gestartet werden, die API getGpuDeviceInfo() unterstützen.
Eine neue Memtrack-HAL-API getGpuDeviceInfo()
muss Informationen über das verwendete GPU-Gerät zurückgeben.
Dies sorgt für eine bessere Speicherabrechnung und Einblick in die DMA-Puffer- und GPU-Speichernutzung. Implementieren Sie den Memtrack AIDL HAL für eine bessere Abrechnung von RAM-Verlust und Speicher. Diese Funktion ist nicht von Google-Diensten abhängig.
Implementierung
Diese Funktion hängt vom AIDL Memtrack HAL ab und Anweisungen zur Implementierung in Android 12 sind als Kommentare im Code enthalten.
Alle HIDL-HALs sollen in zukünftigen Versionen 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();
Um sicherzustellen, dass Ihre Version wie vorgesehen funktioniert, integrieren Sie die Tracepoints in Ihre GPU-Treiber und implementieren Sie die API AIDL memtrack HAL getMemory()
, um den globalen gesamten privaten GPU-Speicher korrekt zurückzugeben, wenn sie mit PID 0 für MemtrackType::GL und MemtrackRecord: aufgerufen wird. FLAG_SMAPS_UNACCOUNTED.