Cette page décrit les différentes améliorations apportées à la comptabilisation de la mémoire dans Android 12.
Statistiques DMA-BUF dans sysfs
Sur Android 11 et Android 12, debugfs
ne peut pas être
installé dans les builds utilisateur. Les statistiques DMA-BUF ont donc été ajoutées à sysfs
dans
Répertoire /sys/kernel/dmabuf/buffers
dans Android 12.
Chemin d'accès | Description |
---|---|
/sys/kernel/dmabuf/buffers
|
Le répertoire /sys/kernel/dmabuf/buffers contient un instantané de l'état interne de chaque DMA-BUF.
/sys/kernel/dmabuf/buffers/<inode_number> contient les statistiques pour
le DMA-BUF avec le numéro de nœud d'index unique <inode_number> .
|
/sys/kernel/dmabuf/buffers/<inode_number>/exporter_name
|
Ce fichier en lecture seule contient le nom de l'exportateur DMA-BUF. |
/sys/kernel/dmabuf/buffers/<inode_number>/size
|
Ce fichier en lecture seule spécifie la taille du DMA-BUF en octets. |
L'API libdmabufinfo
analyse les statistiques sysfs
DMA-BUF pour afficher des statistiques par exportateur et par tampon.
Notez que les pilotes du kernel qui exportent des DMA-BUF doivent définir correctement le champ exp_name
de struct dma_buf_export_info
sur le nom de l'exportateur avant d'appeler l'API dma_buf_export()
pour créer un DMA-BUF.
Cela est nécessaire pour libdmabufinfo
et l'outil dmabuf_dump
afin de dériver des statistiques par exportateur
sont ensuite exposés
dans le rapport de bug.
La méthode dmabuf_dump
L'outil a été modifié pour générer ces informations avec un nouvel argument, -b
.
Statistiques pour le framework de tas DMA-BUF
ION dans GKI 2.0 est abandonné au profit du framework de tas de mémoire DMA-BUF, qui fait partie du noyau Linux en amont.
Les statistiques ION globales suivantes sont suivies dans Android 11 :
- Taille totale des DMA-BUF exportés par chaque tas de mémoire ION
- Taille totale de la mémoire préallouée inutilisée stockée par chaque tas de mémoire ION
Il n'existe pas d'interface permettant d'exposer des statistiques sur les segments de mémoire par ION dans Android 11.
Le tableau suivant compare les interfaces de statistiques ION avec leurs équivalents pour les appareils qui utilisent le framework de tas de mémoire DMA-BUF sous Android 12.
Android 11 ou appareils avec prise en charge d'ION sous Android 12 | Appareils lancés avec des tas de mémoire DMA-BUF sous Android 12 | |
---|---|---|
Statistiques ION par tas de mémoire | Aucune | Extrait des statistiques sysfs DMA-BUF |
Taille totale des DMA-BUF exportés | /sys/kernel/ion/total_heap_size_kb
(N'inclut pas la taille des DMA-BUF exportés par les exportateurs autres que ION) |
Analysé à partir des statistiques sysfs DMA-BUF
(inclut la taille de tous les DMA-BUF exportés). |
Mémoire totale allouée par les segments de mémoire | /sys/kernel/ion/total_pool_size_kb |
/sys/kernel/dma_heap/total_pool_size_kb |
Améliorer la précision du calcul de la RAM perdue
Auparavant, le calcul de la RAM perdue était effectué comme suit :
long final lostRAM
= memInfo.getTotalSizeKb(
) - (totalPss
- totalSwapPss
)
– memInfo.getFreeSizeKb()
– memInfo.getCachedSizeKb()
– kernelUsed
– memInfo.getZramTotalSizeKb()
;
Le composant totalPss
incluait l'utilisation de la mémoire GPU (rendue par l'interface getMemory() du HAL Memtrack). Le composant kernelUsed
comprenait l'utilisation totale de la mémoire du DMA-BUF.
Toutefois, pour les appareils Android, la mémoire du GPU provient des éléments suivants :
- Allocations directes effectuées par le pilote du GPU à l'aide de l'outil d'allocation de pages physiques
- DMA-BUF mappés dans l'espace d'adressage GPU
Par conséquent, les DMA-BUF mappés en mémoire dans l'espace d'adressage du GPU ont été soustraits deux fois lors du calcul de la RAM perdue. Android 12 met en œuvre une solution pour calculer la taille des DMA-BUF mappés au GPU ce qui signifie qu'il n'est pris en compte qu'une seule fois dans le rapport Calcul de la RAM.
La solution détaillée est la suivante :
- L'API HAL Memtrack
getMemory()
lorsqu'il est appelé avec le PID 0 doit indiquer la mémoire totale globale privée par GPU, pour MemtrackType::GL et MemtrackRecord::FLAG_SMAPS_UNACCOUNTED - getMemory() lorsqu'il est appelé avec
PID
0
pour unMemtrackType
autre queGL
ne doit pas échouer. Il doit plutôt renvoyer 0. - La solution tracepoint/eBPF de mémoire GPU ajoutée dans Android 12 tient compte de la mémoire GPU totale. La soustraction de la mémoire privée totale du GPU de la mémoire GPU totale donne le résultat la taille des DMA-BUF mappés dans l'espace d'adressage GPU. La valeur peut ensuite être utilisée pour améliorer la précision des calculs de RAM perdue en tenant compte correctement de l'utilisation de la mémoire du GPU.
- La mémoire GPU privée est incluse dans
totalPss
dans la plupart des implémentations HAL Memtrack et doit donc être dédupliquée avant d'être supprimée delostRAM
.
La solution implémentée est détaillée dans la section suivante.
Supprimer la variabilité Memtrack de la RAM perdue
Étant donné que les implémentations HAL pour Memtrack peuvent varier d'un partenaire à l'autre, la mémoire GPU
inclus dans totalPSS
à partir du HAL n'est pas toujours cohérent. Pour supprimer la variabilité de lostRAM
, la mémoire comptabilisée dans MemtrackType::GRAPHICS
et MemtrackType::GL
est supprimée de totalPss
lors du calcul de lostRAM
.
La mémoire MemtrackType::GRAPHICS
est supprimée de totalPss
et remplacée par la mémoire totalExportedDmabuf
dans le calcul lostRAM
dans ActivityManagerService.java, comme indiqué ci-dessous :
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 mémoire MemtrackType::GL
est supprimée de totalPss
et remplacée par la mémoire GPU privée (gpuPrivateUsage
) dans le calcul lostRAM
dans ActivityManagerService.java, comme indiqué ci-dessous :
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;
Mise à jour du calcul de la perte de RAM
La mémoire GPU privée totale et la mémoire tampon totale de la zone de marché désignée
contenu dans kernelUsed + totalPss
, qui est supprimé de lostRAM
. Ce
Élimine à la fois la double comptabilisation et la variabilité Memtrack liée à la perte de RAM
calcul.
final long lostRAM = memInfo.getTotalSizeKb() - (totalPss - totalSwapPss)
- memInfo.getFreeSizeKb() - memInfo.getCachedSizeKb()
- kernelUsed - memInfo.getZramTotalSizeKb();
Validation
Les tests VTS appliquent la règle selon laquelle les appareils lancés sous Android 12 dotés d'un noyau Linux 5.4 ou version ultérieure sont compatibles avec getGpuDeviceInfo(). API.
Une nouvelle API HAL Memtrack getGpuDeviceInfo()
doit renvoyer des informations sur l'appareil GPU utilisé.
Cela permet une meilleure comptabilisation et visibilité de la mémoire dans le tampon DMA et l'utilisation de la mémoire du GPU. Implémentez le HAL AIDL memtrack pour une meilleure comptabilité de la RAM et de la mémoire perdues. Cette fonctionnalité ne dépend pas des services Google.
Implémentation
Cette fonctionnalité dépend du HAL Memtrack AIDL, et instructions de mise en œuvre sous Android 12 sont inclus dans le code sous forme de commentaires.
Tous les HAL HIDL devraient être convertis en AIDL dans les prochaines versions.
Les API suivantes ont été ajoutées à 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();
Pour vous assurer que votre version fonctionne comme prévu, intégrez les points de trace dans votre GPU
et implémenter l'API HAL getMemory()
AIDL memtrack pour renvoyer correctement
la mémoire GPU privée totale globale lorsqu'elle est appelée avec le PID 0 pour MemtrackType::GL.
et MemtrackRecord::FLAG_SMAPS_UNACCOUNTED.