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 memoria cerrando los procesos menos esenciales para mantener el rendimiento del sistema en niveles aceptables.
Acerca de la presión de la memoria
Un sistema Android que ejecuta varios procesos en paralelo puede encontrarse con situaciones en las que se agota la memoria del sistema y los procesos que requieren más memoria experimentan demoras notables. La presión de memoria, un estado en el que el sistema se está quedando sin memoria, requiere que Android libere memoria (para aliviar la presión) limitando o finalizando procesos no importantes, solicitando a los procesos que liberen recursos almacenados en caché no críticos, etcétera.
Históricamente, Android supervisó la presión de la memoria del sistema con un controlador de eliminación de memoria baja (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 upstream y el lmkd
del espacio del usuario realiza tareas de supervisión de la memoria y finalización de procesos.
Información sobre la detención por presión
Android 10 y versiones posteriores admiten un nuevo modo lmkd
que usa 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 de PSI en el kernel upstream (portado 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 estas demoras afectan directamente la experiencia del usuario, representan una métrica conveniente para determinar la gravedad de la presión de la memoria. El kernel upstream también incluye monitores de PSI que permiten que los procesos privilegiados del espacio del usuario (como lmkd
) especifiquen umbrales para estas demoras y se suscriban a eventos del kernel cuando se supera un umbral.
Monitores de PSI en comparación con los indicadores de vmpressure
Dado que los indicadores de vmpressure
(generados por el kernel para la detección de presión de memoria y utilizados por lmkd
) suelen incluir numerosos 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 computacionales adicionales. El uso de PSI supervisa los resultados y permite detectar con mayor precisión la presión de la memoria, además de minimizar la sobrecarga del filtrado.
Usa monitores de PSI
Para usar los monitores de PSI en lugar de los eventos vmpressure
, configura la propiedad ro.lmk.use_psi
. El valor predeterminado es true
, lo que convierte a los monitores de PSI en el mecanismo predeterminado de detección de presión de la memoria para lmkd
. Dado que los monitores de PSI requieren compatibilidad con el kernel, este debe incluir los parches de portabilidad a versiones anteriores de PSI y compilarse con la compatibilidad con PSI habilitada (CONFIG_PSI=y
).
Desventajas del controlador LMK en el kernel
Android dejó de utilizar el controlador LMK debido a varios problemas, entre los que se incluyen 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 bajo rendimiento provocó un thrashing y no se registraron muertes.
- El controlador del kernel de 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 a menudo personalizaban el controlador para que funcionara en sus dispositivos.
- El controlador de LMK se conectó a la API de reducción de losas, que no se diseñó para operaciones pesadas, como la búsqueda de destinos y la finalización de procesos, lo que ralentizó el proceso de
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. Estos mecanismos incluyen el uso de eventos vmpressure
generados por el kernel o supervisores 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 su importancia.
Cómo usar lmkd de 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 de LMK en el kernel. Dado que lmkd
del espacio de usuario requiere compatibilidad del kernel con 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 eliminación
El espacio del usuario lmkd
admite estrategias de eliminación basadas en eventos vmpressure
o monitores de PSI, su gravedad y otras sugerencias, como la utilización del intercambio. Las estrategias de eliminación difieren entre los dispositivos de memoria insuficiente y los de alto rendimiento:
- En los dispositivos con poca memoria, el sistema debe tolerar una mayor presión de memoria como un modo de funcionamiento normal.
- En los dispositivos de alto rendimiento, la presión de memoria debe considerarse una situación anormal y corregirse antes de que afecte el rendimiento general.
Puedes configurar la estrategia de eliminació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 eliminació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
.
Cómo configurar 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 bajo rendimiento o de alto rendimiento. | false
|
ro.lmk.use_psi |
Usa monitores de PSI (en lugar de eventos vmpressure ). |
true |
ro.lmk.use_minfree_levels
|
Usa umbrales de memoria libre y caché de archivos para tomar decisiones sobre la finalización de procesos (es decir, coincide con la funcionalidad del controlador LMK en el kernel). | false
|
ro.lmk.low
|
Es la puntuación mínima de oom_adj para los procesos aptos para finalizarse en un nivel bajo de vmpressure .
|
1001 (inhabilitado) |
ro.lmk.medium
|
Es la puntuación mínima de oom_adj para los procesos aptos para finalizarse en el nivel medio de vmpressure .
|
800 (servicios almacenados en caché o no esenciales) |
ro.lmk.critical
|
Es la puntuación mínima de oom_adj para los procesos aptos para finalizarse en el nivel crítico de vmpressure .
|
0 (cualquier proceso) |
ro.lmk.critical_upgrade
|
Habilita la actualización al nivel crítico. | false
|
ro.lmk.upgrade_pressure
|
Es el valor máximo de mem_pressure en el que se actualiza el nivel porque el sistema realiza demasiados intercambios.
|
100 (inhabilitado) |
ro.lmk.downgrade_pressure
|
Es el valor mínimo de mem_pressure en el que se ignora un evento de vmpressure porque aún hay suficiente memoria libre disponible.
|
100 (inhabilitado) |
ro.lmk.kill_heaviest_task
|
Elimina la tarea apta más pesada (mejor decisión) en lugar de cualquier tarea apta (decisión rápida). | false
|
ro.lmk.kill_timeout_ms
|
Duración en milisegundos después de una eliminación cuando no se realizará ninguna eliminación adicional. | 0 (inhabilitado) |
ro.lmk.debug
|
Habilita los registros de depuración de 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 de espacio del usuario en Android 11
Android 11 mejora el lmkd
con la introducción de una nueva estrategia de cierre. La estrategia de eliminación usa un mecanismo de PSI para la detección de presión de memoria que se introdujo en Android 10. lmkd
en Android 11 tiene en cuenta los niveles de uso de recursos de memoria y el thrashing para evitar la falta de memoria y la degradación del rendimiento.
Esta estrategia de cierre reemplaza las anteriores y se puede usar en dispositivos de alto rendimiento y con poca RAM (Android Go).
Requisitos del kernel
En el caso de los dispositivos con Android 11, lmkd
requiere las siguientes funciones del kernel:
- Incluye parches de PSI y habilita PSI (hay versiones disponibles en los kernels comunes de Android 4.9, 4.14 y 4.19).
- Incluye parches de compatibilidad con PIDFD (hay versiones anteriores disponibles en los kernels comunes de Android 4.9, 4.14 y 4.19).
- En el caso de los dispositivos con poca RAM, incluye cgroups de memoria.
El kernel debe compilarse con los siguientes parámetros de configuración:
CONFIG_PSI=y
Cómo configurar lmkd en Android 11
La estrategia de cierre de memoria en Android 11 admite los parámetros de ajuste y los valores predeterminados que se indican a continuación. Estas funciones están disponibles en dispositivos de alto rendimiento y con poca RAM.
Propiedad | Usar | Predeterminado | |
---|---|---|---|
Alto rendimiento | Poca RAM | ||
ro.lmk.psi_partial_stall_ms |
Es el umbral de detención de PSI parcial, en milisegundos, para activar la notificación de memoria insuficiente. Si el dispositivo recibe notificaciones de presión en la memoria demasiado tarde, disminuye este valor para activar notificaciones antes. Si las notificaciones de presión en la memoria se activan innecesariamente, aumenta este valor para que el dispositivo sea menos sensible al ruido. | 70 |
200 |
ro.lmk.psi_complete_stall_ms |
Es el umbral completo de detención de PSI, en milisegundos, para activar notificaciones de memoria críticas. Si el dispositivo recibe notificaciones de presión de memoria crítica demasiado tarde, disminuye este valor para activar notificaciones antes. Si las notificaciones de presión de memoria crítica se activan innecesariamente, aumenta este valor para que el dispositivo sea menos sensible al ruido. | 700 |
|
ro.lmk.thrashing_limit |
Cantidad máxima de errores de referencia del conjunto de trabajo como porcentaje del tamaño total de la caché de páginas respaldada por archivos. Los refaltos del conjunto de trabajo por encima de este valor significan que se considera que el sistema está generando una sobrecarga en 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 thrashing. Si el rendimiento del dispositivo se reduce innecesariamente por motivos de saturación, aumenta el valor para permitir más saturación. | 100 |
30 |
ro.lmk.thrashing_limit_decay |
Es la disminución del umbral de pérdida de rendimiento expresada como un porcentaje del umbral original que se usa para reducir el umbral cuando el sistema no se recupera, incluso después de una eliminación. Si el descarte continuo produce eliminaciones innecesarias, disminuye el valor. Si la respuesta a la pérdida continua después de una eliminación es demasiado lenta, aumenta el valor. | 10 |
50 |
ro.lmk.swap_util_max |
Es la cantidad máxima de memoria intercambiada como porcentaje de la memoria total intercambiable. 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 ocurrir cuando las asignaciones no intercambiables generan presión de memoria que no se puede aliviar con el intercambio, ya que la mayor parte de la memoria intercambiable ya se intercambió. El valor predeterminado es 100, lo que inhabilita esta verificación. Si el rendimiento del dispositivo se ve afectado durante la presión en la memoria mientras la utilización del intercambio es alta y el nivel de intercambio libre no disminuye a ro.lmk.swap_free_low_percentage , disminuye el valor para limitar la utilización del intercambio. |
100 |
100 |
Las siguientes variables de ajuste antiguas también funcionan con la nueva estrategia de eliminación.
Propiedad | Usar | Predeterminado | |
---|---|---|---|
Alto rendimiento | Poca RAM | ||
ro.lmk.swap_free_low_percentage |
Es el nivel de intercambio libre como porcentaje del espacio de intercambio total. `lmkd` usa este valor como umbral para determinar cuándo el sistema tiene poco espacio de intercambio. Si `lmkd` finaliza procesos cuando hay demasiado espacio en el intercambio, disminuye el porcentaje. Si las finalizaciones de `lmkd` ocurren demasiado tarde y permiten que se produzcan finalizaciones por OOM, aumenta el porcentaje. | 20 |
10 |
ro.lmk.debug |
Esto habilita los registros de depuración de `lmkd`. Habilita la depuración durante el ajuste. | false |