Daemon de optimización de poca memoria

El proceso del daemon de optimización de poca memoria de Android (lmkd) supervisa el estado de la memoria de un sistema Android en ejecución y reacciona a la alta presión de la memoria finalizando los procesos menos esenciales para mantener el sistema funcionando a niveles aceptables.

Acerca de la presión de la memoria

Un sistema Android que ejecuta varios procesos en paralelo puede encontrarse en situaciones en las que se agota la memoria del sistema y los procesos que requieren más memoria experimentan retrasos notables. Presión de la memoria, un estado en el que el sistema se queda sin memoria, requiere que Android libere memoria (para aliviar la presión) mediante la limitación o la finalización de procesos no importantes, la solicitud de procesos para liberar recursos almacenados en caché no críticos, etcétera.

Históricamente, Android supervisaba la presión de la memoria del sistema con un controlador de optimización de poca memoria (LMK) en el kernel, un mecanismo rígido que depende de valores codificados. A partir del kernel 4.12, el controlador LMK se quitó del kernel superior y el lmkd del espacio del usuario realiza tareas de supervisión de la memoria y finalización de procesos.

Información de demora de presión

Android 10 y versiones posteriores admiten un nuevo modo lmkd que utiliza monitores de información de demora de presión (PSI) del kernel para la detección de presión de la memoria. El conjunto de parches PSI en el kernel superior (transferido a los kernels 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 superior también incluye monitores PSI que permiten que los procesos privilegiados del espacio del usuario (como lmkd) especifiquen umbrales para estos retrasos y se suscriban a eventos del kernel cuando se supera un umbral.

Monitores PSI en comparación con señales vmpressure

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

Usa monitores PSI

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

Desventajas del controlador LMK en el kernel

Android da de baja el controlador LMK debido a varios problemas, incluidos los siguientes:

  • Los dispositivos con poca RAM debían ajustarse de forma agresiva y, aun así, tenían un rendimiento deficiente en cargas de trabajo con una gran caché de páginas activa respaldada por archivos. El rendimiento deficiente provocó hiperpaginación y ninguna finalización.
  • El controlador del kernel LMK se basaba en límites de memoria libre, sin escalamiento según 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 losas, que no se diseñó para operaciones pesadas, como buscar objetivos y finalizarlos, lo que ralentizó el proceso vmscan.

LMKD de espacio del usuario

El lmkd del espacio del usuario implementa la misma funcionalidad que el controlador en el kernel, pero usa mecanismos existentes del kernel para detectar y estimar la presión de la memoria. Entre estos mecanismos, se incluyen el uso de eventos vmpressure generados por el kernel o monitores de información de demora de presión (PSI) para recibir 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 según la importancia del proceso.

Usa lmkd del espacio del usuario en Android 10

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

CONFIG_ANDROID_LOW_MEMORY_KILLER=n
CONFIG_MEMCG=y
CONFIG_MEMCG_SWAP=y

Estrategias de finalización

El lmkd del espacio del usuario admite estrategias de finalización basadas en eventos vmpressure o monitores PSI, su gravedad y otras sugerencias, como el uso de intercambio. Las estrategias de finalización difieren entre los dispositivos de poca memoria y los de alto rendimiento:

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

Puedes configurar la estrategia de finalización con la propiedad ro.config.low_ram.

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

Configura lmkd

Configura lmkd para un dispositivo específico con las siguientes propiedades.

Propiedad Usar Predeterminado
ro.config.low_ram Especifica si el dispositivo es de poca memoria o de alto rendimiento. false
ro.lmk.use_psi Usa monitores PSI (en lugar de eventos vmpressure). true
ro.lmk.use_minfree_levels Usa umbrales de memoria libre y caché de archivos para tomar decisiones de finalización de procesos (es decir, haz coincidir la funcionalidad del controlador LMK en el kernel ). false
ro.lmk.low La puntuación oom_adj mínima para los procesos aptos para finalizarse en un nivel vmpressure bajo. 1001
(inhabilitado)
ro.lmk.medium La puntuación oom_adj mínima para los procesos aptos para finalizarse en un nivel vmpressure medio. 800
(servicios almacenados en caché o no esenciales)
ro.lmk.critical La puntuación mínima oom_adj para los procesos aptos para finalizarse en un nivel vmpressure crítico. 0
(cualquier proceso)
ro.lmk.critical_upgrade Habilita la actualización al nivel crítico. false
ro.lmk.upgrade_pressure La mem_pressure máxima en la que se actualiza el nivel porque el sistema está intercambiando demasiado. 100
(inhabilitado)
ro.lmk.downgrade_pressure La mem_pressure mínima en la que se ignora un evento vmpressure porque aún hay suficiente memoria libre disponible. 100
(inhabilitado)
ro.lmk.kill_heaviest_task Finaliza la tarea apta más pesada (mejor decisión) en comparación con cualquier tarea apta (decisión rápida). false
ro.lmk.kill_timeout_ms Duración en milisegundos después de una finalización cuando no se realizará ninguna finalización adicional. 0
(inhabilitado)
ro.lmk.debug Habilita 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

Lmkd del espacio del usuario en Android 11

Android 11 mejora el lmkd con la introducción de una nueva estrategia de finalización. La estrategia de finalización usa un mecanismo PSI para la detección de presión de la memoria que se introdujo en Android 10. lmkd en Android 11 tiene en cuenta los niveles de uso de recursos de memoria y la hiperpaginación para evitar la falta de memoria y la degradación del rendimiento. Esta estrategia de finalización reemplaza las estrategias anteriores y se puede usar en dispositivos de alto rendimiento y de poca RAM (Android Go).

Requisitos del kernel

Para los dispositivos Android 11, lmkd requiere las siguientes funciones del kernel:

  • Incluye parches PSI y habilita PSI (transferencias disponibles en los kernels comunes de Android 4.9, 4.14 y 4.19).
  • Incluye parches de compatibilidad con PIDFD (transferencias disponibles en los kernels comunes de Android 4.9, 4.14 y 4.19).
  • Para dispositivos de poca RAM, incluye cgroups de memoria.

El kernel debe compilarse con los siguientes parámetros de configuración:

CONFIG_PSI=y

Configura lmkd en Android 11

La estrategia de finalización de memoria en Android 11 admite los botones de ajuste y los valores predeterminados que se indican a continuación. Estas funciones están disponibles en dispositivos de alto rendimiento y de poca RAM.

Propiedad Usar Predeterminado
Alto rendimiento Poca RAM
ro.lmk.psi_partial_stall_ms El umbral de demora PSI parcial, en milisegundos, para activar la notificación de poca memoria. Si el dispositivo recibe notificaciones de presión de la memoria demasiado tarde, disminuye este valor para activar notificaciones anteriores. Si las notificaciones de presión de la memoria se activan de forma innecesaria, aumenta este valor para que el dispositivo sea menos sensible al ruido. 70 200
ro.lmk.psi_complete_stall_ms El umbral de demora PSI completo, en milisegundos, para activar notificaciones de memoria críticas. Si el dispositivo recibe notificaciones de presión de la memoria críticas demasiado tarde, disminuye este valor para activar notificaciones anteriores. Si las notificaciones de presión de la memoria críticas se activan de forma innecesaria, aumenta este valor para que el dispositivo sea menos sensible al ruido. 700
ro.lmk.thrashing_limit La cantidad máxima de errores de conjunto de trabajo como porcentaje del tamaño total de la caché de páginas respaldada por archivos. Los errores de conjunto de trabajo por encima de este valor significan que el sistema se considera que está paginando en exceso su caché de páginas. Si el rendimiento del dispositivo se ve afectado durante la presión de la memoria, disminuye el valor para limitar el exceso de paginación. Si el rendimiento del dispositivo se finaliza de forma innecesaria por motivos de hiperpaginación, aumenta el valor para permitir más hiperpaginación. 100 30
ro.lmk.thrashing_limit_decay La disminución del umbral de hiperpaginación expresada como un porcentaje del umbral original que se usa para disminuir el umbral cuando el sistema no se recupera, incluso después de una finalización. Si la hiperpaginación continua produce finalizaciones innecesarias, disminuye el valor. Si la respuesta al exceso de paginación continuo después de una finalización es demasiado lenta, aumenta el valor. 10 50
ro.lmk.swap_util_max La cantidad máxima de memoria intercambiada como porcentaje de la memoria intercambiable total memoria. Cuando la memoria intercambiada supera este límite, significa que el sistema intercambió la mayor parte de su memoria intercambiable y aún está bajo presión. Esto puede suceder cuando las asignaciones no intercambiables generan presión de la memoria que no se puede aliviar mediante el intercambio porque la mayor parte de la memoria intercambiable ya se intercambió. El valor predeterminado es 100, lo que inhabilita esta verificación de manera efectiva. Si el rendimiento del dispositivo se ve afectado durante la presión de la memoria mientras el uso de intercambio es alto y el nivel de intercambio libre no disminuye a ro.lmk.swap_free_low_percentage, disminuye el valor para limitar el uso de intercambio. 100 100

Los siguientes botones de ajuste antiguos también funcionan con la nueva estrategia de finalización.

Propiedad Usar Predeterminado
Alto rendimiento Poca RAM
ro.lmk.swap_free_low_percentage El nivel de intercambio libre como porcentaje del espacio de intercambio total. `lmkd` usa este valor como umbral para considerar que el sistema no tiene espacio de intercambio. Si `lmkd` finaliza mientras hay demasiado espacio en el intercambio, disminuye el porcentaje. Si las finalizaciones de `lmkd` ocurren demasiado tarde, lo que permite que se produzcan finalizaciones de OOM, aumenta el porcentaje. 20 10
ro.lmk.debug Esto habilita los registros de depuración `lmkd`. Habilita la depuración durante el ajuste. false