Android 17 et versions ultérieures sont compatibles avec le Memory Limiter, un service système qui surveille et limite l'utilisation de la mémoire des processus d'application à l'aide de Linux cgroup v2. Le limiteur de mémoire empêche les applications individuelles de consommer trop de mémoire système, ce qui réduit la pression sur la mémoire à l'échelle du système et empêche l'arrêt agressif des processus critiques en cas de mémoire insuffisante (OOM, Out Of Memory).
Mécanisme
Le limiteur de mémoire s'intègre au service Activity Manager (AMS) pour suivre les événements du cycle de vie des processus et les changements d'état. Le limiteur de mémoire applique des limites de mémoire à l'aide du système de fichiers cgroup v2 du noyau Linux.
Pour utiliser le limiteur de mémoire, le noyau de l'appareil doit être compatible avec le contrôleur cgroup v2 et memory. Le service s'appuie spécifiquement sur les attributs suivants :
memory.high- : limite flexible. Lorsque cette limite est dépassée, le processus est limité et le noyau tente de récupérer de la mémoire.
memory.swap.max- Limite la quantité d'espace d'échange que le processus peut utiliser.
Impact sur les applications
Les applications qui ne dépassent pas leurs limites de mémoire ne sont pas affectées par le Memory Limiter.
Lorsqu'une application dépasse sa limite memory.high, le noyau évince la mémoire de l'application soutenue par des fichiers et échange sa mémoire anonyme pour maintenir l'application dans la limite. En raison de l'éviction et de l'échange, l'application peut s'exécuter plus lentement.
Dans le pire des cas, si l'application continue d'allouer de la mémoire anonyme et que l'appareil manque d'espace d'échange, l'application peut ne pas réussir à allouer de la mémoire et est donc susceptible de planter.
Surveillance des processus
Le Memory Limiter surveille les processus d'application (UID >= 10000) par défaut. Les processus système sont généralement exemptés pour aider à vérifier la stabilité du système principal.
Le limiteur de mémoire attribue des limites de mémoire en fonction de l'état du processus :
Les processus visibles sont perceptibles par l'utilisateur, comme les activités de premier plan, les services de premier plan ou d'autres états perceptibles par les saccades.
Les processus non visibles sont des processus d'arrière-plan qui n'interagissent pas avec l'utilisateur et ne sont pas visibles par celui-ci.
Le tableau suivant met en correspondance des états de processus spécifiques avec des limites de mémoire :
| État du processus | Limite de mémoire |
|---|---|
PERSISTENT | Pas de restriction |
PERSISTENT_UI | Pas de restriction |
TOP | Visible |
BOUND_TOP | Visible |
FOREGROUND_SERVICE | Non visible |
BOUND_FOREGROUND_SERVICE | Non visible |
IMPORTANT_FOREGROUND | Visible |
IMPORTANT_BACKGROUND | Non visible |
TRANSIENT_BACKGROUND | Non visible |
BACKUP | Non visible |
SERVICE | Non visible |
RECEIVER | Non visible |
TOP_SLEEPING | Visible |
HEAVY_WEIGHT | Non visible |
HOME | Non visible |
LAST_ACTIVITY | Non visible |
CACHED_ACTIVITY | En cache |
CACHED_ACTIVITY_CLIENT | En cache |
CACHED_RECENT | En cache |
CACHED_EMPTY | En cache |
Dans l'état mis en cache, les processus sont figés, puis récupérés au maximum.
Lorsqu'un processus dépasse sa limite memory.high attribuée, le Memory Limiter détecte l'événement et peut déclencher des actions de débogage, comme la capture d'un profil de mémoire ou la journalisation d'une anomalie dans statsd.
Configuration
Configurez le limiteur de mémoire à l'aide d'un fichier XML situé sur la partition vendor. La configuration vous permet d'ajuster les limites de mémoire absolues en fonction des contraintes de mémoire spécifiques de l'appareil.
Chemin d'accès au fichier :
/vendor/etc/memory-limiter-config.xmlConfiguration par défaut : si le fichier de configuration est introuvable, illisible ou non valide, le limiteur de mémoire est désactivé.
Format XML
Le fichier de configuration suit le schéma défini dans memory-limiter-config.xsd. Le fichier vous permet de définir plusieurs ensembles de limites. Le service choisit la meilleure correspondance en fonction de la RAM disponible sur l'appareil. Toutes les valeurs de mémoire sont définies en mébioctets (Mio).
<MemoryLimiterConfig>
<version>1</version>
<configList>
<limitSet>
<!-- Limits for a phone with at least 14G of ram: 8G/4G/4G/4G -->
<minimumRequiredMemTotal>14336</minimumRequiredMemTotal>
<memVisible>8192</memVisible>
<memNotVisible>4096</memNotVisible>
<swapVisible>4096</swapVisible>
<swapNotVisible>4096</swapNotVisible>
</limitSet>
</configList>
</MemoryLimiterConfig>
version- Entier positif identifiant la version de la configuration. Cette valeur doit être égale à 1.
minimumRequiredMemTotal- La mémoire système disponible minimale requise pour que cet ensemble de limites soit valide.
memVisible- Limite de mémoire (
memory.high) autorisée pour les processus visibles. memNotVisible- Limite de mémoire (
memory.high) autorisée pour les processus non visibles. swapVisible- Limite d'échange (
memory.swap.max) autorisée pour les processus visibles. swapNotVisible- La limite d'échange (
memory.swap.max) autorisée pour les processus non visibles.
Consignes concernant la limite de mémoire des appareils
Lorsque vous configurez des limites de mémoire pour votre appareil, tenez compte des consignes suivantes :
Adapter les limites aux capacités matérielles : les OEM d'appareils peuvent définir des limites adaptées aux capacités matérielles de leurs appareils. Android recommande les plages suivantes :
- Processus visibles : au moins la moitié et au maximum les deux tiers de la RAM physique totale.
- Processus non visibles : entre 1/4 et 1/3 de la RAM physique totale. Les OEM peuvent prendre différentes décisions en fonction des capacités et des cas d'utilisation des appareils.
Aucune API d'exécution pour les applications : depuis Android 17 (SDK 37), les applications ne disposent pas d'API pour interroger les limites de mémoire au moment de l'exécution. Les OEM doivent en tenir compte et éviter de définir des limites trop basses, en s'assurant que les applications ne les atteignent pas lors de cas d'utilisation raisonnables.
Configuration universelle : les limites s'appliquent à tous les processus d'application sur l'appareil, y compris les applications préinstallées. Aucune liste d'autorisation ne permet d'exempter certaines applications de ces limites.
Modifier la configuration
Pour modifier les limites à l'échelle du système :
- Modifier
/vendor/etc/memory-limiter-config.xml. - Redémarrez l'appareil ou
system_serverpour que les modifications prennent effet.
Commandes shell
La commande am memory-limiter vous permet, à vous et aux développeurs, d'interagir avec le service au moment de l'exécution pour le développement et les tests :
am memory-limiter <SUB-COMMAND>état
La sous-commande status indique l'état opérationnel du limiteur de mémoire :
adb shell am memory-limiter statusExemple de résultat :
Memory limiter
enabled monitoring=true ignored=none
visibleMem=1948MB visibleSwap=974MB
notVisibleMem=974MB notVisibleSwap=487MB
started=36 watched=36 watch-failed=0
events=0 processes=36 process-hwm=36
Voici les principaux champs de la sortie :
monitoring- Indique si le limiteur surveille activement les processus.
visibleMemetnotVisibleMem- Indiquez les limites de mémoire absolues calculées pour chaque état.
events- Nombre de fois où un processus a dépassé sa limite.
processes- Nombre de processus surveillés.
ignorer
La sous-commande ignore exclut temporairement un UID ou tous les processus de la limitation. Cette action est utile pour les tests de performances ou pour autoriser une application spécifique à dépasser ses limites.
adb shell am memory-limiter ignore 10087 // Ignore a specific UIDadb shell am memory-limiter ignore all // Ignore all processes (effectively disables limiting)adb shell am memory-limiter ignore none // Resume normal operation
manuel
La sous-commande manual remplace les limites calculées pour un processus spécifique (par ID de processus ou PID) par une valeur absolue personnalisée en mégaoctets (Mo) :
adb shell am memory-limiter manual 1234 1024 // Set a 1024 MB limit for PID 1234adb shell am memory-limiter manual 1234 none // Remove the manual override for PID 1234
Les remplacements manuels ne s'appliquent qu'au cycle de vie du processus. Si le processus redémarre, il revient aux limites par défaut en fonction de son état.