Daemon do Low memory killer

O processo do daemon do Android Low Memory Killer (lmkd) monitora o estado de memória de um sistema Android em execução e reage à alta pressão de memória encerrando os processos menos essenciais para manter o desempenho do sistema em níveis aceitáveis.

Sobre a pressão de memória

Um sistema Android que executa vários processos em paralelo pode encontrar situações em que a memória do sistema está esgotada e processos que exigem mais memória apresentam atrasos perceptíveis. A pressão de memória, um estado em que o sistema está com pouca memória, exige que o Android libere memória (para aliviar a pressão) restringindo ou encerrando processos sem importância, solicitando processos para liberar recursos não críticos armazenados em cache e assim por diante.

Historicamente, o Android monitorava a pressão da memória do sistema usando um driver de LMK no kernel, um mecanismo rígido que depende de valores codificados. A partir do kernel 4.12, o driver LMK é removido do kernel upstream, e o lmkd do espaço do usuário executa tarefas de monitoramento de memória e de eliminação de processos.

Informações sobre compressão de pressão

O Android 10 e versões mais recentes oferecem suporte a um novo modo lmkd que usa monitores de informação de pouca pressão (PSI, na sigla em inglês) do kernel para detecção de pressão da memória. O conjunto de patches do PSI no kernel upstream (retornado para kernels 4.9 e 4.14) mede o tempo que as tarefas são atrasadas devido a falta de memória. Como esses atrasos afetam diretamente a experiência do usuário, eles representam uma métrica conveniente para determinar a gravidade da pressão de memória. O kernel upstream também inclui monitores PSI que permitem que processos de espaço do usuário privilegiados (como lmkd) especifiquem limites para esses atrasos e se inscrevam em eventos do kernel quando um limite é violado.

Monitores PSI x sinais de vmpressure

Como os sinais vmpressure (gerados pelo kernel para detecção de pressão de memória e usados por lmkd) geralmente incluem vários falsos positivos, o lmkd precisa realizar a filtragem para determinar se a memória está sob pressão real. Isso resulta em ativações lmkd desnecessárias e no uso de outros recursos computacionais. O uso de monitores de PSI resulta em uma detecção de pressão de memória mais precisa e minimiza a sobrecarga de filtragem.

Usar monitores de PSI

Para usar monitores PSI em vez de eventos vmpressure, configure a propriedade ro.lmk.use_psi. O padrão é true, fazendo com que o PSI monitore o mecanismo padrão de detecção de pressão da memória para lmkd. Como os monitores de PSI exigem suporte ao kernel, o kernel precisa incluir os patches de backport do PSI e ser compilado com o suporte ao PSI ativado (CONFIG_PSI=y).

Desvantagens do driver LMK no kernel

O Android descontinua o driver LMK devido a vários problemas, incluindo:

  • Os dispositivos com pouca RAM precisavam ser ajustados de forma agressiva e, mesmo assim, apresentavam um desempenho ruim em cargas de trabalho com um grande cache de página ativo com suporte a arquivos. O desempenho ruim resultou em sobrecarga e nenhuma interrupção.
  • O driver do kernel LMK dependia de limites de memória livre, sem dimensionamento baseado na pressão de memória.
  • Devido à rigidez do design, os parceiros geralmente personalizavam o driver para que ele funcionasse nos dispositivos.
  • O driver do LMK foi conectado à API de redutor de laje, que não foi projetada para operações pesadas, como pesquisar e eliminar alvos, o que atrasava o processo vmscan.

lmkd do espaço do usuário

O lmkd do espaço do usuário implementa a mesma funcionalidade do driver no kernel, mas usa mecanismos do kernel para detectar e estimar a pressão da memória. Esses mecanismos incluem o uso de eventos vmpressure gerados pelo kernel ou de monitores de informações de bloqueio de pressão (PSI, na sigla em inglês) para receber notificações sobre níveis de pressão de memória e o uso de recursos de cgroup de memória para limitar os recursos de memória alocados para cada processo com base na importância do processo.

Usar o lmkd do espaço do usuário no Android 10

No Android 9 e versões mais recentes, o espaço do usuário lmkd será ativado se um driver LMK no kernel não for detectado. Como o lmkd do espaço do usuário exige suporte do kernel para cgroups de memória, o kernel precisa ser compilado com as seguintes configurações:

CONFIG_ANDROID_LOW_MEMORY_KILLER=n
CONFIG_MEMCG=y
CONFIG_MEMCG_SWAP=y

Estratégias de eliminação

O espaço do usuário lmkd é compatível com estratégias de destruição baseadas em eventos vmpressure ou monitores PSI, na gravidade deles e em outras dicas, como utilização de troca. As estratégias de desligamento são diferentes entre dispositivos de pouca memória e de alto desempenho:

  • Em dispositivos com pouca memória, o sistema precisa tolerar uma pressão de memória mais alta como um modo normal de operação.
  • Em dispositivos de alto desempenho, a pressão da memória precisa ser considerada uma situação anormal e corrigida antes que ela afete o desempenho geral.

É possível configurar a estratégia de eliminação usando a propriedade ro.config.low_ram. Saiba mais em Configuração de RAM baixa.

O lmkd do espaço do usuário também oferece suporte a um modo legado em que ele toma decisões de eliminação usando as mesmas estratégias do driver LMK no kernel, ou seja, limites de memória livre e cache de arquivos. Para ativar o modo legado, defina a propriedade ro.lmk.use_minfree_levels como true.

Configurar lmkd

Configure o lmkd para um dispositivo específico usando as propriedades abaixo.

Propriedade Uso Padrão
ro.config.low_ram Especifique se o dispositivo tem pouca RAM ou é de alto desempenho. false
ro.lmk.use_psi Use monitores de PSI (em vez de eventos vmpressure). true
ro.lmk.use_minfree_levels Use os limites de memória livre e de cache de arquivos para tomar decisões de encerramento de processos, ou seja, corresponda à funcionalidade do driver LMK no kernel. false
ro.lmk.low A pontuação mínima oom_adj para processos qualificados para serem encerrados no nível vmpressure baixo. 1001
(desativado)
ro.lmk.medium A pontuação mínima de oom_adj para processos qualificados para encerramento no nível médio de vmpressure. 800
(serviços armazenados em cache ou não essenciais)
ro.lmk.critical A pontuação mínima de oom_adj para processos qualificados para encerramento no nível crítico de vmpressure. 0
(qualquer processo)
ro.lmk.critical_upgrade Ativar upgrade para o nível crítico. false
ro.lmk.upgrade_pressure O mem_pressure máximo em que o nível é atualizado porque o sistema está fazendo muitas trocas. 100
(desativado)
ro.lmk.downgrade_pressure O mem_pressure mínimo em que um evento vmpressure é ignorado porque ainda há memória disponível suficiente. 100
(desativado)
ro.lmk.kill_heaviest_task Elimine a tarefa qualificada mais pesada (melhor decisão) em vez de qualquer tarefa qualificada (decisão rápida). false
ro.lmk.kill_timeout_ms Duração em milissegundos após uma eliminação quando nenhuma outra eliminação será feita. 0
(desativado)
ro.lmk.debug Ative os registros de depuração do lmkd. false

Exemplo de configuração do 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 do espaço do usuário no Android 11

O Android 11 melhora o lmkd com a introdução de uma nova estratégia de eliminação. A estratégia de eliminação usa um mecanismo PSI para detecção de pressão da memória introduzido no Android 10. O lmkd no Android 11 considera os níveis de uso de recursos de memória e a sobrecarga para evitar a privação de memória e a degradação do desempenho. Essa estratégia de eliminação substitui as anteriores e pode ser usada em dispositivos de alto desempenho e com pouca memória RAM (Android Go).

Requisitos do kernel

Para dispositivos Android 11, o lmkd requer os seguintes recursos do kernel:

  • Inclua patches de PSI e ative o PSI (backports disponíveis nos kernels comuns do Android 4.9, 4.14 e 4.19).
  • Incluir patches de compatibilidade com PIDFD, backports disponíveis nos kernels comuns do Android 4.9, 4.14 e 4.19.
  • Para dispositivos com pouca memória RAM, inclua grupos de controle de memória.

O kernel precisa ser compilado com as seguintes configurações:

CONFIG_PSI=y

Configurar o lmkd no Android 11

A estratégia de eliminação de memória no Android 11 oferece suporte aos controles de ajuste e padrões listados abaixo. Esses recursos funcionam em dispositivos de alto desempenho e com pouca memória RAM.

Propriedade Uso Padrão
Alto desempenho RAM baixa
ro.lmk.psi_partial_stall_ms O limite de paralisação parcial do PSI, em milissegundos, para acionar a notificação de memória baixa. Se o dispositivo receber notificações de pressão de memória tarde demais, diminua esse valor para acionar notificações mais antigas. Se as notificações de pressão de memória forem acionadas desnecessariamente, aumente esse valor para tornar o dispositivo menos sensível ao ruído. 70 200
ro.lmk.psi_complete_stall_ms O limite completo de inatividade de PSI, em milissegundos, para acionar notificações de memória críticas. Se o dispositivo receber notificações de pressão de memória tarde demais, diminua esse valor para acionar notificações mais antigas. Se as notificações de pressão crítica de memória forem acionadas desnecessariamente, aumente esse valor para tornar o dispositivo menos sensível a ruídos. 700
ro.lmk.thrashing_limit A quantidade máxima de revisões de conjunto de trabalho como uma porcentagem do tamanho total da página de cache de arquivos. As revisões de conjunto de trabalho acima desse valor significam que o sistema está sendo considerado como um cache de página. Se o desempenho do dispositivo for afetado durante a pressão da memória, diminua o valor para limitar o thrashing. Se o desempenho do dispositivo for encerrado desnecessariamente por motivos de thrashing, aumente o valor para permitir mais thrashing. 100 30
ro.lmk.thrashing_limit_decay O declínio do limite de sobrecarga expresso como uma porcentagem do limite original usado para diminuir o limite quando o sistema não se recupera, mesmo após uma interrupção. Se o uso excessivo contínuo produzir mortes desnecessárias, diminua o valor. Se a resposta à sobrecarga contínua após uma interrupção for muito lenta, aumente o valor. 10 50
ro.lmk.swap_util_max A quantidade máxima de memória trocada como uma porcentagem da memória total trocável. Quando a memória trocada aumenta acima desse limite, significa que o sistema trocou a maior parte da memória intercambiável e ainda está sob pressão. Isso pode acontecer quando alocações não trocáveis geram pressão de memória que não pode ser aliviada pela troca, porque a maioria da memória trocável já foi trocada. O valor padrão é 100, o que desativa essa verificação. Se o desempenho do dispositivo for afetado durante a pressão da memória enquanto a utilização de troca estiver alta e o nível de troca livre não estiver caindo para ro.lmk.swap_free_low_percentage, diminua o valor para limitar a utilização de troca. 100 100

Os botões de ajuste antigos a seguir também funcionam com a nova estratégia de desativação.

Propriedade Uso Padrão
Alto desempenho Pouca RAM
ro.lmk.swap_free_low_percentage O nível de troca livre como uma porcentagem do espaço de troca total. "lmkd" usa esse valor como um limite para considerar o sistema como um espaço de troca com falta. Se o `lmkd` for encerrado quando houver muito espaço em troca, diminua a porcentagem. Se o `lmkd` for encerrado muito tarde, permitindo que o encerramento por falta de memória aconteça, aumente a porcentagem. 20 10
ro.lmk.debug Isso ativa os registros de depuração "lmkd". Ative a depuração durante o ajuste. false