Questa pagina descrive i vari miglioramenti al calcolo della memoria introdotti in Android 12.
Statistiche DMA-BUF in sysfs
In Android 11 e Android 12, debugfs
non può essere
montato nelle build utente. Pertanto, le statistiche DMA-BUF sono state aggiunte a sysfs
nella directory
/sys/kernel/dmabuf/buffers
in Android 12.
Percorso | Descrizione |
---|---|
/sys/kernel/dmabuf/buffers
|
La directory /sys/kernel/dmabuf/buffers contiene uno snapshot dello stato interno di ogni DMA-BUF.
/sys/kernel/dmabuf/buffers/<inode_number> contiene le statistiche per
il DMA-BUF con il numero di inodi univoco <inode_number> .
|
/sys/kernel/dmabuf/buffers/<inode_number>/exporter_name
|
Questo file di sola lettura contiene il nome dell'esportatore DMA-BUF. |
/sys/kernel/dmabuf/buffers/<inode_number>/size
|
Questo file di sola lettura specifica la dimensione del DMA-BUF in byte. |
L'API libdmabufinfo
analizza le statistiche sysfs
DMA-BUF per esporre le statistiche per esportatore e per buffer.
Tieni presente che i driver del kernel che esportano DMA-BUF devono impostare correttamente il campo exp_name
di struct dma_buf_export_info
sul nome dell'esportatore prima di invocare l'API dma_buf_export()
per creare un DMA-BUF.
Questo è necessario per libdmabufinfo
e lo strumento dmabuf_dump
per ricavare le statistiche per esportatore che vengono poi esposte nel report di bug.
Lo strumento dmabuf_dump è stato modificato per restituire queste informazioni con un nuovo argomento, -b
.
Statistiche per il framework degli heap DMA-BUF
ION in GKI 2.0 è stato ritirato a favore del framework degli heap DMA-BUF, che fa parte del kernel Linux upstream.
In Android 11 vengono monitorate le seguenti statistiche globali di ION:
- Dimensione totale delle DMA-BUF esportate da ogni heap ION
- Dimensione totale della memoria preallocata inutilizzata archiviata da ogni heap ION
In Android 11 non è disponibile un'interfaccia per esporre le statistiche relative all'heap per ION.
La tabella seguente mette a confronto le interfacce delle statistiche ION con le relative controparti per i dispositivi che utilizzano il framework heap DMA-BUF in Android 12.
Android 11 o dispositivi con supporto ION in Android 12 | Dispositivi lanciati con heap DMA-BUF in Android 12 | |
---|---|---|
Statistiche ION per heap | Nessuno | Analizzato in base alle statistiche di sistema DMA-BUF |
Dimensioni totali dei DMA-BUF esportati | /sys/kernel/ion/total_heap_size_kb
(Non include le dimensioni delle DMA-BUF esportate da esportatori non ION) |
Analizzata dalle statistiche di sysfs DMA-BUF
(include le dimensioni di tutte le DMA-BUF esportate). |
Memoria totale raggruppata per heap | /sys/kernel/ion/total_pool_size_kb |
/sys/kernel/dma_heap/total_pool_size_kb |
Migliora la precisione del calcolo della RAM persa
In precedenza, il calcolo della RAM persa veniva eseguito nel seguente modo:
finale lungo lostRAM
= memInfo.getTotalSizeKb(
) - (totalPss
- totalSwapPss
)
- memInfo.getFreeSizeKb()
- memInfo.getCachedSizeKb()
- kernelUsed
- memInfo.getZramTotalSizeKb()
;
Il componente totalPss
includeva l'utilizzo della memoria GPU (restituito dall'interfaccia getMemory() dell'HAL Memtrack). Il componente kernelUsed
includeva l'utilizzo totale della memoria DMA-BUF.
Tuttavia, per i dispositivi Android, la memoria GPU proveniva da quanto segue:
- Allocazioni dirette effettuate dal driver della GPU utilizzando l'allocatore di pagine fisiche
- DMA-BUF mappate nello spazio di indirizzi GPU
Pertanto, i DMA-BUF mappati nella memoria nello spazio degli indirizzi GPU sono stati sottratti due volte al momento del calcolo della RAM persa. Android 12 implementa una soluzione per calcolare le dimensioni dei DMA-BUF mappati nello spazio indirizzi della GPU, il che significa che vengono conteggiate una sola volta nel calcolo della RAM persa.
I dettagli della soluzione sono i seguenti:
- L'API HAL Memtrack
getMemory()
quando viene chiamata con PID 0 deve segnalare la memoria privata GPU totale globale per MemtrackType::GL e MemtrackRecord::FLAG_SMAPS_UNACCOUNTED. - getMemory() quando viene chiamato con
PID
0
per unMemtrackType
diverso daGL
non deve avere esito negativo. Deve invece restituire 0. - La soluzione tracepoint/eBPF per la memoria GPU aggiunta in Android 12 tiene conto della memoria GPU totale. Sottraendo la memoria privata della GPU totale dalla memoria GPU totale si ottengono le dimensioni dei DMA-BUF mappati nello spazio degli indirizzi della GPU. Il valore può essere utilizzato per migliorare l'accuratezza dei calcoli della RAM persa tenendo conto correttamente dell'utilizzo della memoria GPU.
- La memoria GPU privata è inclusa in
totalPss
nella maggior parte delle implementazioni HAL Memtrack e pertanto deve essere deduplicata prima di rimuoverla dalostRAM
.
La soluzione implementata è descritta in dettaglio nella sezione successiva.
Rimuovi la variabilità Memtrack dalla RAM persa
Poiché le implementazioni dell'HAL di Memtrack possono variare da un partner all'altro, la memoria GPU
inclusa in totalPSS
dell'HAL non è sempre coerente. Per rimuovere la variabilità da lostRAM
, la memoria considerata in MemtrackType::GRAPHICS
e MemtrackType::GL
viene rimossa da totalPss
durante il calcolo di lostRAM
.
La memoria MemtrackType::GRAPHICS
viene rimossa da totalPss
e sostituita con la memoria totalExportedDmabuf
nel calcolo lostRAM
in ActivityManagerService.java come mostrato di seguito:
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;
La memoria MemtrackType::GL
viene rimossa da totalPss
e sostituita con la memoria GPU privata (gpuPrivateUsage
) nel calcolo di lostRAM
in ActivityManagerService.java come mostrato di seguito:
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;
Calcolo della RAM persa aggiornato
Sia la memoria GPU privata totale sia la memoria buffer DMA esportata totale sono contenute in kernelUsed + totalPss
, che viene rimosso da lostRAM
. Ciò
elimina sia il doppio conteggio sia la variabilità Memtrack dal calcolo della RAM
persa.
final long lostRAM = memInfo.getTotalSizeKb() - (totalPss - totalSwapPss)
- memInfo.getFreeSizeKb() - memInfo.getCachedSizeKb()
- kernelUsed - memInfo.getZramTotalSizeKb();
Convalida
I test VTS applicano la regola che i dispositivi avviati in Android 12 con un kernel Linux versione 5.4 o successive supportano l'API getGpuDeviceInfo().
Una nuova API HAL Memtrack getGpuDeviceInfo()
deve restituire informazioni sul dispositivo GPU in uso.
In questo modo, viene migliorata la conta della memoria e la visibilità dell'utilizzo della memoria della GPU e del buffer DMA. Implementa l'HAL AIDL memtrack per una migliore contabilizzazione della RAM e della memoria persa. Questa funzionalità non dipende dai servizi Google.
Implementazione
Questa funzionalità dipende dall'AIDL Memtrack HAL e le istruzioni per implementarla in Android 12 sono incluse nel codice sotto forma di commenti.
È prevista la conversione di tutti gli HAL HIDL in AIDL nelle release future.
Le seguenti API sono state aggiunte a 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();
Per assicurarti che la tua versione funzioni come previsto, integra i tracepoint nei driver della GPU e implementa l'API AIDL memtrack HAL getMemory()
per restituire correttamente la memoria privata GPU totale globale quando viene chiamata con PID 0 per MemtrackType::GL e MemtrackRecord::FLAG_SMAPS_UNACCOUNTED.