En esta página, se describen las diversas mejoras en el registro de memoria que se introdujeron en Android 12.
Estadísticas de DMA-BUF en sysfs
En Android 11 y Android 12, debugfs
no se puede activar en compilaciones de usuario. Por lo tanto, las estadísticas de DMA-BUF se agregaron a sysfs
en el
Directorio /sys/kernel/dmabuf/buffers
en Android 12.
Ruta | Descripción |
---|---|
/sys/kernel/dmabuf/buffers
|
El directorio /sys/kernel/dmabuf/buffers contiene una instantánea del
el estado interno de cada DMA-BUF.
/sys/kernel/dmabuf/buffers/<inode_number> contiene las estadísticas del DMA-BUF con el número de inodo único <inode_number> .
|
/sys/kernel/dmabuf/buffers/<inode_number>/exporter_name
|
Este archivo de solo lectura contiene el nombre del exportador de DMA-BUF. |
/sys/kernel/dmabuf/buffers/<inode_number>/size
|
Este archivo de solo lectura especifica el tamaño del DMA-BUF en bytes. |
La libdmabufinfo
La API analiza las estadísticas de sysfs
de DMA-BUF para exponer las estadísticas por exportador y por búfer.
Ten en cuenta que los controladores de kernel que exportan DMA-BUF deben establecer el exp_name
de struct dma_buf_export_info
correctamente al nombre del exportador antes
invocar la API de dma_buf_export()
para crear un DMA-BUF
Esto es necesario para que libdmabufinfo
y la herramienta dmabuf_dump
deriven estadísticas por exportador que luego se exponen en bugreport.
El dmabuf_dump
se modificó para mostrar esta información con un nuevo argumento, -b
.
Estadísticas del framework de los montones de DMA-BUF
ION en GKI 2.0 dejará de estar disponible a favor del framework de montones de DMA-BUF, que forma parte del kernel de Linux upstream.
En Android 11, se realiza un seguimiento de las siguientes estadísticas globales de ION:
- Tamaño total de los DMA-BUF exportados por cada montón de ION
- Es el tamaño total de la memoria preasignada sin usar que almacena cada montón de ION.
No hay una interfaz disponible para exponer estadísticas del montón por ION en Android 11.
En la siguiente tabla, se comparan las interfaces de estadísticas de ION con sus counterparts para dispositivos que usan el framework de montón DMA-BUF en Android 12.
Android 11 o dispositivos que se lanzan con compatibilidad con ION en Android 12 | Dispositivos que se lanzan con montones de DMA-BUF en Android 12 | |
---|---|---|
Estadísticas de ION por montón | Ninguno | Se analiza a partir de las estadísticas de sysfs de DMA-BUF. |
Tamaño total de los DMA-BUF exportados | /sys/kernel/ion/total_heap_size_kb
(no incluye el tamaño de los DMA-BUF exportados por exportadores que no son de ION) |
Análisis de las estadísticas del sistema DMA-BUF
(incluye el tamaño de todos los DMA-BUF exportados). |
Memoria total agrupada por montón | /sys/kernel/ion/total_pool_size_kb |
/sys/kernel/dma_heap/total_pool_size_kb |
Cómo mejorar la precisión del cálculo de la pérdida de RAM
Anteriormente, el cálculo de la pérdida de RAM se realizaba de la siguiente manera:
lostRAM
final largo = memInfo.getTotalSizeKb(
) - (totalPss
- totalSwapPss
)
- memInfo.getFreeSizeKb()
- memInfo.getCachedSizeKb()
- kernelUsed
- memInfo.getZramTotalSizeKb()
;
El componente totalPss
incluía el uso de memoria de la GPU (que muestra la interfaz getMemory() del HAL de Memtrack). El componente kernelUsed
incluía el uso total de memoria de DMA-BUF.
Sin embargo, en el caso de los dispositivos Android, la memoria de la GPU provenía de lo siguiente:
- Asignaciones directas que realiza el controlador de GPU mediante un asignador de página físico
- DMA-BUF asignados al espacio de direcciones de la GPU
Por lo tanto, los DMA-BUF que se asignaron a la memoria en el espacio de direcciones de la GPU se restaron dos veces cuando se calculó la RAM perdida. Android 12 implementa una solución para calcular el tamaño de los DMA-BUF asignados en el espacio de direcciones de la GPU, lo que significa que se registra solo una vez en el cálculo de RAM perdida.
Los detalles de la solución son los siguientes:
- Cuando se llama a la API de HAL de Memtrack
getMemory()
con el PID 0, debe informar la memoria privada total global de la GPU para MemtrackType::GL y MemtrackRecord::FLAG_SMAPS_UNACCOUNTED. - getMemory() cuando se llama con
PID
0
para unMemtrackType
que no seaGL
no debe fallar. En su lugar, debe mostrar 0. - La solución de punto de seguimiento de memoria de GPU/eBPF que se agregó en Android 12 tiene en cuenta la memoria total de la GPU. Si se resta la memoria privada total de la GPU de la memoria total de la GPU, se obtiene el tamaño de los DMA-BUF asignados en el espacio de direcciones de la GPU. El valor se puede usar para mejorar la precisión de los cálculos de pérdida de RAM teniendo en cuenta correctamente el uso de memoria de la GPU.
- La memoria privada de la GPU se incluye en
totalPss
en la mayoría de las implementaciones de HAL de Memtrack y, por lo tanto, se debe anular antes de quitarla delostRAM
.
La solución implementada se detalla en la siguiente sección.
Quita la variabilidad de Memtrack de la memoria RAM perdida
Dado que las implementaciones de HAL de Memtrack pueden variar entre los socios, la memoria de la GPU incluida en totalPSS
del HAL no siempre es coherente. Para quitar la variabilidad de lostRAM
, la memoria registrada en MemtrackType::GRAPHICS
y MemtrackType::GL
se quita de totalPss
durante el cálculo de lostRAM
.
La memoria MemtrackType::GRAPHICS
se quita de totalPss
y se reemplaza por la memoria totalExportedDmabuf
en el cálculo lostRAM
en ActivityManagerService.java, como se muestra a continuación:
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;
Se quitó la memoria MemtrackType::GL
de totalPss
y se reemplazó por
memoria de GPU privada (gpuPrivateUsage
) en el cálculo de lostRAM
en
ActivityManagerService.java
como se muestra a continuación:
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;
Actualización del cálculo de la pérdida de RAM
Tanto la memoria de GPU privada total como la memoria de búfer de DMA exportada se
incluido en kernelUsed + totalPss
, que se quitó de lostRAM
. Esta
Elimina la variabilidad de recuento doble y Memtrack de la memoria RAM perdida.
cálculo.
final long lostRAM = memInfo.getTotalSizeKb() - (totalPss - totalSwapPss)
- memInfo.getFreeSizeKb() - memInfo.getCachedSizeKb()
- kernelUsed - memInfo.getZramTotalSizeKb();
Validación
Las pruebas de VTS aplican la regla de que los dispositivos que se inician en Android 12 con un kernel de Linux versión 5.4 o posterior admiten la API de getGpuDeviceInfo().
Una nueva API de HAL de Memtrack getGpuDeviceInfo()
debe mostrar información sobre el dispositivo de GPU en uso.
Esto proporciona una mejor contabilización de la memoria y visibilidad del búfer de DMA y la GPU. el uso de memoria. Implementa el HAL de AIDL de memtrack para mejorar el registro de RAM y memoria perdidos. Esta función no depende de los servicios de Google.
Implementación
Esta función depende de la HAL del Memtrack de AIDL. y las instrucciones para implementarla en Android 12 se incluyen en el código como comentarios.
Se planea que todos los HAL de HIDL se conviertan a AIDL en versiones futuras.
Se agregaron las siguientes APIs 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();
Para asegurarte de que tu versión funcione según lo previsto, integra los puntos de seguimiento en los controladores de la GPU y, luego, implementa la API de getMemory()
de HAL de memtrack de AIDL para mostrar correctamente la memoria privada total global de la GPU cuando se llame con PID 0 para MemtrackType::GL y MemtrackRecord::FLAG_SMAPS_UNACCOUNTED.