Daemon de tueur de mémoire faible

Le processus du daemon du tueur de mémoire faible Android (lmkd) surveille l'état de la mémoire d'un système Android en cours d'exécution et réagit à une forte pression de mémoire en arrêtant les processus les moins essentiels pour maintenir le système à un niveau de performances acceptable.

À propos de la sollicitation de la mémoire

Un système Android exécutant plusieurs processus en parallèle peut rencontrer des situations où la mémoire système est épuisée et où les processus qui nécessitent plus de mémoire subissent des retards notables. La pression de la mémoire, un état dans lequel le système manque de mémoire, oblige Android à libérer de la mémoire (pour atténuer la pression) en limitant ou en arrêtant les processus non importants, en demandant aux processus de libérer les ressources mises en cache non critiques, etc.

Historiquement, Android surveillait la saturation de la mémoire système à l'aide d'un pilote LMK (low memory killer) intégré au noyau, un mécanisme rigide qui dépend de valeurs codées en dur. Depuis le noyau 4.12, le pilote LMK a été supprimé du noyau en amont et l'espace utilisateur lmkd effectue des tâches de surveillance de la mémoire et d'arrêt des processus.

Informations sur le décrochage par perte de portance

Android 10 et les versions ultérieures sont compatibles avec un nouveau mode lmkd qui utilise des moniteurs d'informations sur la pression du noyau (PSI) pour détecter la pression de la mémoire. Le patchset PSI dans le noyau en amont (rétroporté vers les noyaux 4.9 et 4.14) mesure le temps pendant lequel les tâches sont retardées en raison d'un manque de mémoire. Ces retards affectant directement l'expérience utilisateur, ils constituent une métrique pratique pour déterminer la gravité de la pression mémoire. Le noyau en amont inclut également des moniteurs PSI qui permettent aux processus d'espace utilisateur privilégiés (tels que lmkd) de spécifier des seuils pour ces délais et de s'abonner aux événements du noyau lorsqu'un seuil est dépassé.

Signaux de pression de la pompe à vide et signaux de pression du système d'admission

Étant donné que les signaux vmpressure (générés par le noyau pour la détection de la pression mémoire et utilisés par lmkd) incluent souvent de nombreux faux positifs, lmkd doit effectuer un filtrage pour déterminer si la mémoire est réellement sous pression. Cela entraîne des réveils lmkd inutiles et l'utilisation de ressources de calcul supplémentaires. L'utilisation de PSI pour surveiller les résultats permet de détecter plus précisément la pression mémoire et de minimiser la surcharge de filtrage.

Utiliser les moniteurs PSI

Pour utiliser les moniteurs PSI au lieu des événements vmpressure, configurez la propriété ro.lmk.use_psi. La valeur par défaut est true, ce qui fait des moniteurs PSI le mécanisme par défaut de détection de la pression mémoire pour lmkd. Étant donné que les moniteurs PSI nécessitent la prise en charge du noyau, celui-ci doit inclure les correctifs de rétroportage PSI et être compilé avec la prise en charge PSI activée (CONFIG_PSI=y).

Inconvénients du pilote LMK dans le noyau

Android abandonne le pilote LMK en raison de plusieurs problèmes, y compris :

  • Les appareils à faible RAM devaient être réglés de manière agressive, et même dans ce cas, leurs performances étaient médiocres pour les charges de travail avec un grand cache de pages actif soutenu par des fichiers. Les mauvaises performances ont entraîné un thrashing et aucun kill.
  • Le pilote de noyau LMK s'appuyait sur des limites de mémoire libre, sans mise à l'échelle en fonction de la pression sur la mémoire.
  • En raison de la rigidité de la conception, les partenaires ont souvent personnalisé le pilote pour qu'il fonctionne sur leurs appareils.
  • Le pilote LMK était rattaché à l'API de réduction de la taille des blocs, qui n'était pas conçue pour les opérations lourdes telles que la recherche de cibles et leur suppression, ce qui ralentissait le processus vmscan.

Userspace lmkd

L'espace utilisateur lmkd implémente la même fonctionnalité que le pilote dans le noyau, mais utilise les mécanismes de noyau existants pour détecter et estimer la pression mémoire. Ces mécanismes incluent l'utilisation d'événements vmpressure générés par le noyau ou de moniteurs d'informations sur les blocages dus à la pression (PSI) pour recevoir des notifications sur les niveaux de pression de la mémoire, ainsi que l'utilisation de fonctionnalités de cgroup de mémoire pour limiter les ressources de mémoire allouées à chaque processus en fonction de son importance.

Utiliser lmkd dans l'espace utilisateur sous Android 10

Dans Android 9 et versions ultérieures, l'espace utilisateur lmkd s'active si aucun pilote LMK dans le noyau n'est détecté. Étant donné que l'espace utilisateur lmkd nécessite la prise en charge du noyau pour les cgroups de mémoire, le noyau doit être compilé avec les paramètres de configuration suivants :

CONFIG_ANDROID_LOW_MEMORY_KILLER=n
CONFIG_MEMCG=y
CONFIG_MEMCG_SWAP=y

Stratégies d'arrêt

L'espace utilisateur lmkd est compatible avec les stratégies d'arrêt basées sur les événements vmpressure ou les moniteurs PSI, leur gravité et d'autres indications telles que l'utilisation du swap. Les stratégies d'arrêt diffèrent entre les appareils à faible mémoire et ceux à hautes performances :

  • Sur les appareils à faible mémoire, le système doit tolérer une pression de mémoire plus élevée comme mode de fonctionnement normal.
  • Sur les appareils hautes performances, la pression sur la mémoire doit être considérée comme une situation anormale et corrigée avant qu'elle n'affecte les performances globales.

Vous pouvez configurer la stratégie d'arrêt à l'aide de la propriété ro.config.low_ram.

L'espace utilisateur lmkd est également compatible avec un ancien mode dans lequel il prend des décisions d'arrêt à l'aide des mêmes stratégies que le pilote LMK dans le noyau (c'est-à-dire les seuils de mémoire libre et de cache de fichiers). Pour activer l'ancien mode, définissez la propriété ro.lmk.use_minfree_levels sur true.

Configurer lmkd

Configurez lmkd pour un appareil spécifique à l'aide des propriétés suivantes.

Propriété Utiliser Par défaut
ro.config.low_ram Indiquez si l'appareil est un appareil à faible RAM ou à hautes performances. false
ro.lmk.use_psi Utilisez des moniteurs PSI (au lieu des événements vmpressure). true
ro.lmk.use_minfree_levels Utilisez les seuils de mémoire libre et de cache de fichiers pour prendre des décisions d'arrêt de processus (c'est-à-dire, faites correspondre la fonctionnalité du pilote LMK dans le noyau). false
ro.lmk.low Score oom_adj minimal pour les processus pouvant être arrêtés à un niveau vmpressure faible. 1001
(désactivé)
ro.lmk.medium Score oom_adj minimal pour les processus pouvant être arrêtés au niveau vmpressure moyen. 800
(services mis en cache ou non essentiels)
ro.lmk.critical Score oom_adj minimal pour les processus pouvant être arrêtés au niveau critique vmpressure. 0
(tout processus)
ro.lmk.critical_upgrade Activez la mise à niveau au niveau critique. false
ro.lmk.upgrade_pressure mem_pressure maximal auquel le niveau est augmenté, car le système échange trop de données. 100
(désactivé)
ro.lmk.downgrade_pressure mem_pressure minimal auquel un événement vmpressure est ignoré, car il reste suffisamment de mémoire libre. 100
(désactivé)
ro.lmk.kill_heaviest_task Arrêt de la tâche éligible la plus lourde (meilleure décision) par rapport à n'importe quelle tâche éligible (décision rapide). false
ro.lmk.kill_timeout_ms Durée en millisecondes après une fermeture forcée lorsqu'aucune autre fermeture forcée ne sera effectuée. 0
(désactivé)
ro.lmk.debug Activez les journaux de débogage lmkd. false

Exemple de configuration de l'appareil :

PRODUCT_PROPERTY_OVERRIDES += \
    ro.lmk.low=1001 \
    ro.lmk.medium=800 \
    ro.lmk.critical=0 \
    ro.lmk.critical_upgrade=false \
    ro.lmk.upgrade_pressure=100 \
    ro.lmk.downgrade_pressure=100 \
    ro.lmk.kill_heaviest_task=true

lmkd de l'espace utilisateur dans Android 11

Android 11 améliore lmkd en introduisant une nouvelle stratégie d'arrêt. La stratégie d'arrêt utilise un mécanisme PSI pour la détection de la pression de mémoire introduit dans Android 10. lmkd dans Android 11 tient compte des niveaux d'utilisation des ressources mémoire et du thrashing pour éviter la saturation de la mémoire et la dégradation des performances. Cette stratégie d'arrêt remplace les stratégies précédentes et peut être utilisée sur les appareils hautes performances et à faible RAM (Android Go).

Exigences concernant le noyau

Pour les appareils Android 11, lmkd nécessite les fonctionnalités de noyau suivantes :

  • Incluez les correctifs PSI et activez PSI (rétroportages disponibles dans les noyaux communs Android 4.9, 4.14 et 4.19).
  • Incluez les correctifs de prise en charge PIDFD (rétroportages disponibles dans les noyaux communs Android 4.9, 4.14 et 4.19).
  • Pour les appareils à faible RAM, incluez les cgroups de mémoire.

Le noyau doit être compilé avec les paramètres de configuration suivants :

CONFIG_PSI=y

Configurer lmkd dans Android 11

La stratégie de suppression de la mémoire dans Android 11 est compatible avec les boutons de réglage et les valeurs par défaut listés ci-dessous. Ces fonctionnalités sont disponibles sur les appareils à hautes performances et à faible RAM.

Propriété Utiliser Par défaut
Hautes performances RAM faible
ro.lmk.psi_partial_stall_ms Seuil de blocage PSI partiel, en millisecondes, pour déclencher une notification de mémoire faible. Si l'appareil reçoit les notifications de saturation de la mémoire trop tard, diminuez cette valeur pour déclencher des notifications plus tôt. Si les notifications de pression de la mémoire se déclenchent inutilement, augmentez cette valeur pour rendre l'appareil moins sensible au bruit. 70 200
ro.lmk.psi_complete_stall_ms Seuil d'arrêt PSI complet, en millisecondes, pour déclencher des notifications de mémoire critiques. Si l'appareil reçoit des notifications de saturation critique de la mémoire trop tard, diminuez cette valeur pour déclencher des notifications plus tôt. Si les notifications de pression mémoire critique se déclenchent inutilement, augmentez cette valeur pour rendre l'appareil moins sensible au bruit. 700
ro.lmk.thrashing_limit Nombre maximal de refauts de l'ensemble de travail en pourcentage de la taille totale du cache de pages adossé à un fichier. Les refaults de l'ensemble de travail supérieurs à cette valeur signifient que le système est considéré comme thrashing son cache de pages. Si les performances de l'appareil sont affectées par la pression sur la mémoire, diminuez la valeur pour limiter le thrashing. Si les performances de l'appareil sont inutilement interrompues pour des raisons de thrashing, augmentez la valeur pour autoriser davantage de thrashing. 100 30
ro.lmk.thrashing_limit_decay Diminution du seuil de thrashing exprimée en pourcentage du seuil d'origine utilisé pour abaisser le seuil lorsque le système ne récupère pas, même après un arrêt. Si le thrashing continu génère des arrêts inutiles, diminuez la valeur. Si la réponse au thrashing continu après un arrêt est trop lente, augmentez la valeur. 10 50
ro.lmk.swap_util_max Quantité maximale de mémoire permutée, exprimée en pourcentage de la mémoire totale pouvant être permutée. Lorsque la mémoire d'échange dépasse cette limite, cela signifie que le système a échangé la majeure partie de sa mémoire échangeable et qu'il est toujours sous pression. Cela peut se produire lorsque des allocations non échangeables génèrent une pression sur la mémoire qui ne peut pas être soulagée par l'échange, car la majeure partie de la mémoire échangeable est déjà échangée. La valeur par défaut est 100, ce qui désactive ce contrôle. Si les performances de l'appareil sont affectées par la saturation de la mémoire alors que l'utilisation du swap est élevée et que le niveau de swap disponible ne descend pas à ro.lmk.swap_free_low_percentage, diminuez la valeur pour limiter l'utilisation du swap. 100 100

Les anciens boutons de réglage suivants fonctionnent également avec la nouvelle stratégie de mise à mort.

Propriété Utiliser Par défaut
Hautes performances RAM faible
ro.lmk.swap_free_low_percentage Niveau de swap libre exprimé en pourcentage de l'espace de swap total. `lmkd` utilise cette valeur comme seuil pour déterminer quand le système est à court d'espace de swap. Si `lmkd` s'arrête alors qu'il y a trop d'espace dans le fichier d'échange, diminuez le pourcentage. Si les arrêts `lmkd` se produisent trop tard, ce qui permet aux arrêts OOM de se produire, augmentez le pourcentage. 20 10
ro.lmk.debug Cela permet d'activer les journaux de débogage `lmkd`. Activez le débogage pendant le réglage. false