Demonio asesino de poca memoria

El proceso del demonio asesino de memoria baja de Android ( lmkd ) monitorea el estado de la memoria de un sistema Android en ejecución y reacciona a la alta presión de la memoria eliminando los procesos menos esenciales para mantener el rendimiento del sistema a niveles aceptables.

Sobre la presión de la memoria

Un sistema Android que ejecuta varios procesos en paralelo puede encontrar situaciones en las que la memoria del sistema se agota y los procesos que requieren más memoria experimentan retrasos notables. La presión de la memoria , un estado en el que el sistema se está quedando sin memoria, requiere que Android libere memoria (para aliviar la presión) acelerando o matando procesos sin importancia, solicitando procesos para liberar recursos en caché no críticos, etc.

Históricamente, Android monitoreaba la presión de la memoria del sistema mediante un controlador LMK (low memory killer) en el núcleo, un mecanismo rígido que depende de valores codificados de forma rígida. A partir del kernel 4.12, el controlador LMK se elimina del kernel ascendente y el espacio de usuario lmkd realiza tareas de monitoreo de memoria y eliminación de procesos.

Información de pérdida de presión

Android 10 y versiones posteriores admiten un nuevo modo lmkd que usa monitores de información de bloqueo de presión (PSI) del núcleo para la detección de presión de memoria. El conjunto de parches de PSI en el núcleo ascendente (retrocedido a los núcleos 4.9 y 4.14) mide la cantidad de tiempo que se retrasan las tareas como resultado de la escasez de memoria. Como estos retrasos afectan directamente la experiencia del usuario, representan una métrica conveniente para determinar la gravedad de la presión de la memoria. El kernel ascendente también incluye monitores PSI que permiten que los procesos de espacio de usuario privilegiado (como lmkd ) especifiquen umbrales para estos retrasos y se suscriban a eventos del kernel cuando se infringe un umbral.

Monitores PSI frente a señales de vmpresión

Debido a que las señales de vmpressure (generadas por el kernel para la detección de la presión de la memoria y utilizadas por lmkd ) a menudo incluyen numerosos falsos positivos, lmkd debe realizar un filtrado para determinar si la memoria está bajo presión real. Esto da como resultado activaciones innecesarias lmkd y el uso de recursos computacionales adicionales. El uso de monitores PSI da como resultado una detección de presión de memoria más precisa y minimiza la sobrecarga de filtrado.

Uso de monitores PSI

Para usar monitores PSI en lugar de eventos vmpressure , configure la propiedad ro.lmk.use_psi . El valor predeterminado es true , lo que hace que los monitores PSI sean el mecanismo predeterminado de detección de presión de memoria para lmkd . Debido a que los monitores de PSI requieren compatibilidad con el kernel, el kernel debe incluir los parches de backport de PSI y compilarse con la compatibilidad con PSI habilitada ( CONFIG_PSI=y ).

Inconvenientes del controlador LMK en el kernel

Android desaprueba el controlador LMK debido a una serie de problemas, que incluyen:

  • Los dispositivos con poca RAM tenían que ajustarse agresivamente, e incluso entonces tendrían un rendimiento deficiente en cargas de trabajo con un gran caché de página activo respaldado por archivos. El mal desempeño resultó en palizas y sin muertes.
  • El controlador del kernel LMK se basó en los límites de memoria libre, sin escalado basado en la presión de la memoria.
  • Debido a la rigidez del diseño, los socios solían personalizar el controlador para que funcionara en sus dispositivos.
  • El controlador LMK se conectó a la API de reducción de losa, que no fue diseñada para operaciones pesadas como buscar objetivos y matarlos, lo que ralentizó el proceso de vmscan .

espacio de usuario lmkd

El espacio de usuario lmkd implementa la misma funcionalidad que el controlador del núcleo, pero utiliza los mecanismos del núcleo existentes para detectar y estimar la presión de la memoria. Dichos mecanismos incluyen el uso de eventos vmpressure generados por el kernel o monitores de información de bloqueo de presión (PSI) para obtener notificaciones sobre los niveles de presión de la memoria y el uso de funciones de cgroup de memoria para limitar los recursos de memoria asignados a cada proceso en función de la importancia del proceso.

Usando el espacio de usuario lmkd en Android 10

En Android 9 y versiones posteriores, el espacio de usuario lmkd activa si no se detecta un controlador LMK en el kernel. Debido a que el espacio de usuario lmkd requiere soporte de kernel para cgroups de memoria, el kernel debe compilarse con los siguientes ajustes de configuración:

CONFIG_ANDROID_LOW_MEMORY_KILLER=n
CONFIG_MEMCG=y
CONFIG_MEMCG_SWAP=y

Matar estrategias

Userspace lmkd admite estrategias de eliminación basadas en eventos de vmpressure o monitores PSI, su gravedad y otras sugerencias, como la utilización de intercambio. Las estrategias de eliminación difieren entre los dispositivos de memoria baja y los de alto rendimiento:

  • En dispositivos con poca memoria, el sistema debe tolerar una mayor presión de memoria como modo de funcionamiento normal.
  • En los dispositivos de alto rendimiento, la presión de la memoria debe verse como una situación anormal y corregirse antes de que afecte el rendimiento general.

Puede configurar la estrategia de eliminación mediante la propiedad ro.config.low_ram . Para obtener más información, consulte Configuración de RAM baja .

Userspace lmkd también admite un modo heredado en el que toma decisiones de finalización utilizando las mismas estrategias que el controlador LMK en el kernel (es decir, memoria libre y umbrales de caché de archivos). Para habilitar el modo heredado, establezca la propiedad ro.lmk.use_minfree_levels en true .

Configuración de lmkd

Configure lmkd para un dispositivo específico usando las siguientes propiedades.

Propiedad Usar Defecto
ro.config.low_ram Especifique si el dispositivo es un dispositivo con poca memoria RAM o de alto rendimiento. false
ro.lmk.use_psi Use monitores PSI (en lugar de eventos de vmpressure ). true
ro.lmk.use_minfree_levels Utilice la memoria libre y los umbrales de caché de archivos para tomar decisiones de terminación de procesos (es decir, igualar la funcionalidad del controlador LMK en el kernel). false
ro.lmk.low La puntuación mínima de oom_adj para los procesos aptos para eliminarse a un nivel de presión de vmpressure bajo. 1001
(discapacitado)
ro.lmk.medium La puntuación mínima de oom_adj para los procesos aptos para eliminarse en un nivel de vmpressure medio. 800
(servicios almacenados en caché o no esenciales)
ro.lmk.critical La puntuación mínima de oom_adj para los procesos aptos para eliminarse en un nivel de presión de vmpressure crítico. 0
(cualquier proceso)
ro.lmk.critical_upgrade Habilite la actualización al nivel crítico. false
ro.lmk.upgrade_pressure La mem_pressure máxima a la que se actualiza el nivel porque el sistema se está intercambiando demasiado. 100
(discapacitado)
ro.lmk.downgrade_pressure La mem_pressure mínima en la que se ignora un evento de vmpressure porque todavía hay suficiente memoria libre disponible. 100
(discapacitado)
ro.lmk.kill_heaviest_task Elimine la tarea elegible más pesada (mejor decisión) frente a cualquier tarea elegible (decisión rápida). true
ro.lmk.kill_timeout_ms Duración en milisegundos después de una muerte cuando no se realizará ninguna muerte adicional. 0
(discapacitado)
ro.lmk.debug Habilite los registros de depuración lmkd . false

Ejemplo de configuración del dispositivo:

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

Espacio de usuario lmkd en Android 11

Android 11 mejora el lmkd al presentar una nueva estrategia de asesinato. La estrategia de eliminación utiliza un mecanismo PSI para la detección de presión de memoria introducido en Android 10. lmkd en Android 11 tiene en cuenta los niveles de uso de recursos de memoria y la paliza para evitar el agotamiento de la memoria y la degradación del rendimiento. Esta estrategia de destrucción reemplaza a las estrategias anteriores y se puede usar tanto en dispositivos de alto rendimiento como de RAM baja (Android Go).

Requisitos del núcleo

Para dispositivos con Android 11, lmkd requiere las siguientes características del kernel:

  • Incluya parches de PSI y habilite PSI (backports disponibles en los núcleos comunes de Android 4.9, 4.14 y 4.19).
  • Incluya parches de compatibilidad con PIDFD (backports disponibles en los kernels comunes de Android 4.9, 4.14 y 4.19).
  • Para dispositivos con poca RAM, incluya cgroups de memoria.

El kernel debe compilarse con los siguientes ajustes de configuración:

CONFIG_PSI=y

Configuración de lmkd en Android 11

La estrategia de destrucción de memoria en Android 11 es compatible con las perillas de ajuste y los valores predeterminados que se enumeran a continuación. Estas funciones funcionan tanto en dispositivos de alto rendimiento como en dispositivos con poca memoria RAM.

Propiedad Usar Defecto
Alto rendimiento RAM baja
ro.lmk.psi_partial_stall_ms El umbral de bloqueo de PSI parcial, en milisegundos, para activar la notificación de memoria baja. Si el dispositivo recibe notificaciones de presión de memoria demasiado tarde, disminuya este valor para activar notificaciones anteriores. Si las notificaciones de presión de memoria se activan innecesariamente, aumente este valor para que el dispositivo sea menos sensible al ruido. 70 200
ro.lmk.psi_complete_stall_ms El umbral completo de bloqueo de PSI, en milisegundos, para activar notificaciones de memoria crítica. Si el dispositivo recibe notificaciones de presión de memoria crítica demasiado tarde, disminuya este valor para activar notificaciones anteriores. Si las notificaciones de presión de memoria crítica se activan innecesariamente, aumente este valor para que el dispositivo sea menos sensible al ruido. 700
ro.lmk.thrashing_limit La cantidad máxima de valores predeterminados del conjunto de trabajo como porcentaje del tamaño total de la memoria caché de la página respaldada por el archivo. Los valores predeterminados del conjunto de trabajo por encima de este valor significan que se considera que el sistema está golpeando su caché de página. Si el rendimiento del dispositivo se ve afectado durante la presión de la memoria, disminuya el valor para limitar la paliza. Si el rendimiento del dispositivo se interrumpe innecesariamente por motivos de paliza, aumente el valor para permitir más paliza. 100 30
ro.lmk.thrashing_limit_decay El decaimiento del umbral de paliza expresado como un porcentaje del umbral original utilizado para reducir el umbral cuando el sistema no se recupera, incluso después de una muerte. Si la paliza continua produce muertes innecesarias, disminuya el valor. Si la respuesta a la paliza continua después de una muerte es demasiado lenta, aumente el valor. 10 50
ro.lmk.swap_util_max La cantidad máxima de memoria intercambiada como porcentaje de la memoria intercambiable total. Cuando la memoria intercambiada crece por encima de este límite, significa que el sistema intercambió la mayor parte de su memoria intercambiable y todavía está bajo presión. Esto puede suceder cuando las asignaciones no intercambiables generan una presión de memoria que no se puede aliviar mediante el intercambio porque la mayor parte de la memoria intercambiable ya se ha intercambiado. El valor predeterminado es 100, lo que deshabilita efectivamente esta verificación. Si el rendimiento del dispositivo se ve afectado durante la presión de la memoria mientras la utilización de intercambio es alta y el nivel de intercambio libre no cae a ro.lmk.swap_free_low_percentage , reduzca el valor para limitar la utilización de intercambio. 100 100

Las siguientes perillas de afinación antiguas también funcionan con la nueva estrategia de matar.

Propiedad Usar Defecto
Alto rendimiento RAM baja
ro.lmk.swap_free_low_percentage El nivel de intercambio libre como porcentaje del espacio de intercambio total. `lmkd` usa este valor como un umbral para considerar el sistema como falto de espacio de intercambio. Si `lmkd` mata mientras hay demasiado espacio en el intercambio, disminuya el porcentaje. Si las eliminaciones de `lmkd` ocurren demasiado tarde, lo que permite que ocurran eliminaciones de OOM, aumente el porcentaje. 20 10
ro.lmk.debug Esto habilita los registros de depuración `lmkd`. Habilite la depuración durante el ajuste. false