Daemon assassino com pouca memória

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

Sobre pressão de memória

Um sistema Android executando vários processos em paralelo pode encontrar situações em que a memória do sistema se esgota e os 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), limitando ou eliminando processos sem importância, solicitando processos para liberar recursos não críticos em cache e assim por diante.

Historicamente, o Android monitorava a pressão da memória do sistema usando um driver LMK (Low Memory Killer) 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 espaço do usuário lmkd executa tarefas de monitoramento de memória e eliminação de processos.

Informações de parada de pressão

O Android 10 e versões posteriores oferecem suporte a um novo modo lmkd que usa monitores de informações de travamento de pressão do kernel (PSI) para detecção de pressão de memória. O patchset PSI no kernel upstream (portado para os kernels 4.9 e 4.14) mede a quantidade de tempo que as tarefas são atrasadas como resultado de 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 de usuário privilegiados (como lmkd ) especifiquem limites para esses atrasos e assinem eventos do kernel quando um limite for violado.

Monitores PSI versus sinais de pressão vm

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, lmkd deve realizar a filtragem para determinar se a memória está sob pressão real. Isso resulta em ativações desnecessárias lmkd e no uso de recursos computacionais adicionais. O uso de monitores PSI resulta em uma detecção de pressão de memória mais precisa e minimiza a sobrecarga de filtragem.

Usando monitores 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 de memória para lmkd . Como os monitores PSI requerem suporte de kernel, o kernel deve incluir os patches de backport PSI e ser compilado com suporte PSI habilitado ( CONFIG_PSI=y ).

Desvantagens do driver LMK no kernel

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

  • Dispositivos com pouca RAM tiveram que ser ajustados agressivamente e, mesmo assim, teriam um desempenho ruim em cargas de trabalho com cache de página ativo apoiado por arquivos grandes. O mau desempenho resultou em surras e nenhuma morte.
  • O driver do kernel LMK dependia de limites de memória livre, sem escalonamento baseado na pressão da memória.
  • Devido à rigidez do design, os parceiros frequentemente personalizavam o driver para que funcionasse em seus dispositivos.
  • O driver LMK conectou-se à API do encolhedor de placas, que não foi projetada para operações pesadas, como procurar alvos e matá-los, o que retardava o processo vmscan .

Espaço do usuário lmkd

O espaço do usuário lmkd implementa a mesma funcionalidade do driver no kernel, mas usa mecanismos de kernel existentes para detectar e estimar a pressão de memória. Esses mecanismos incluem o uso de eventos vmpressure gerados pelo kernel ou monitores de informações de sobrepressão (PSI) para obter 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.

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

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

CONFIG_ANDROID_LOW_MEMORY_KILLER=n
CONFIG_MEMCG=y
CONFIG_MEMCG_SWAP=y

Estratégias de matar

O Userspace lmkd oferece suporte a estratégias de eliminação baseadas em eventos vmpressure ou monitores PSI, sua gravidade e outras dicas, como utilização de swap. As estratégias de eliminação diferem entre dispositivos com pouca memória e dispositivos de alto desempenho:

  • Em dispositivos com pouca memória, o sistema deve tolerar maior pressão de memória como modo normal de operação.
  • Em dispositivos de alto desempenho, a pressão da memória deve ser vista como uma situação anormal e corrigida antes que afete o desempenho geral.

Você pode configurar a estratégia kill usando a propriedade ro.config.low_ram . Para obter detalhes, consulte Configuração de memória RAM baixa .

O Userspace lmkd também oferece suporte a um modo legado no qual ele toma decisões de eliminação usando as mesmas estratégias do driver LMK no kernel (ou seja, memória livre e limites de cache de arquivo). Para ativar o modo legado, configure a propriedade ro.lmk.use_minfree_levels como true .

Configurando o lmkd

Configure lmkd para um dispositivo específico usando as propriedades a seguir.

Propriedade Usar Padrão
ro.config.low_ram Especifique se o dispositivo é um dispositivo com pouca RAM ou de alto desempenho. false
ro.lmk.use_psi Use monitores PSI (em vez de eventos vmpressure ). true
ro.lmk.use_minfree_levels Use memória livre e limites de cache de arquivo para tomar decisões de eliminação de processos (ou seja, corresponder à funcionalidade do driver LMK no kernel). false
ro.lmk.low A pontuação oom_adj mínima para processos elegíveis para serem eliminados em baixo nível vmpressure . 1001
(desabilitado)
ro.lmk.medium A pontuação oom_adj mínima para processos elegíveis para serem eliminados no nível médio vmpressure . 800
(serviços armazenados em cache ou não essenciais)
ro.lmk.critical A pontuação oom_adj mínima para processos elegíveis para serem eliminados no nível crítico vmpressure . 0
(qualquer processo)
ro.lmk.critical_upgrade Habilite a atualização para o nível crítico. false
ro.lmk.upgrade_pressure O mem_pressure máximo no qual o nível é atualizado porque o sistema está trocando demais. 100
(desabilitado)
ro.lmk.downgrade_pressure O mem_pressure mínimo no qual um evento vmpressure é ignorado porque ainda há memória livre suficiente disponível. 100
(desabilitado)
ro.lmk.kill_heaviest_task Elimine a tarefa elegível mais pesada (melhor decisão) versus qualquer tarefa elegível (decisão rápida). true
ro.lmk.kill_timeout_ms Duração em milissegundos após uma morte, quando nenhuma morte adicional será realizada. 0
(desabilitado)
ro.lmk.debug Habilite os logs de depuração 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

Espaço do usuário lmkd no Android 11

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

Requisitos do kernel

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

  • Incluir patches PSI e ativar PSI (backports disponíveis nos kernels comuns do Android 4.9, 4.14 e 4.19).
  • Inclui patches de suporte PIDFD (backports disponíveis nos kernels comuns do Android 4.9, 4.14 e 4.19).
  • Para dispositivos com pouca RAM, inclua cgroups de memória.

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

CONFIG_PSI=y

Configurando lmkd no Android 11

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

Propriedade Usar Padrão
Alta performance RAM baixa
ro.lmk.psi_partial_stall_ms O limite de travamento parcial do PSI, em milissegundos, para acionar a notificação de pouca memória. Se o dispositivo receber notificações de pressão de memória tarde demais, diminua esse valor para acionar notificações mais cedo. Se as notificações de pressão de memória forem acionadas desnecessariamente, aumente esse valor para tornar o dispositivo menos sensível a ruídos. 70 200
ro.lmk.psi_complete_stall_ms O limite completo de paralisação do PSI, em milissegundos, para acionar notificações críticas de memória. Se o dispositivo receber notificações críticas de pressão de memória tarde demais, diminua esse valor para acionar notificações mais cedo. Se notificações críticas de pressão 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 refaults do conjunto de trabalho como uma porcentagem do tamanho total do pagecache com suporte de arquivo. Refaults do conjunto de trabalho acima desse valor significam que o sistema está sobrecarregando seu pagecache. Se o desempenho do dispositivo for afetado durante a pressão da memória, diminua o valor para limitar o desgaste. Se o desempenho do dispositivo for interrompido desnecessariamente por motivos de surra, aumente o valor para permitir mais surra. 100 30
ro.lmk.thrashing_limit_decay A redução do limite de thrashing expressa como uma porcentagem do limite original usado para diminuir o limite quando o sistema não se recupera, mesmo após uma eliminação. Se a surra contínua produzir mortes desnecessárias, diminua o valor. Se a resposta à surra contínua após uma morte for muito lenta, aumente o valor. 10 50
ro.lmk.swap_util_max A quantidade máxima de memória trocada como uma porcentagem do total de memória trocável. Quando a memória trocada ultrapassa esse limite, significa que o sistema trocou a maior parte de sua memória trocável e ainda está sob pressão. Isso pode acontecer quando as alocações não trocáveis ​​estão gerando pressão de memória que não pode ser aliviada pela troca porque a maior parte da memória trocável já foi trocada. O valor padrão é 100, o que desativa efetivamente essa verificação. Se o desempenho do dispositivo for afetado durante a pressão da memória enquanto a utilização de swap estiver alta e o nível de swap livre não estiver caindo para ro.lmk.swap_free_low_percentage , diminua o valor para limitar a utilização de swap. 100 100

Os botões de ajuste antigos a seguir também funcionam com a nova estratégia de matar.

Propriedade Usar Padrão
Alta performance RAM baixa
ro.lmk.swap_free_low_percentage O nível de swap livre como porcentagem do espaço de swap total. `lmkd` usa este valor como um limite para quando considerar o sistema como sem espaço de troca. Se `lmkd` matar enquanto houver muito espaço na troca, diminua a porcentagem. Se as mortes do `lmkd` acontecerem tarde demais, permitindo que as mortes do OOM aconteçam, aumente a porcentagem. 20 10
ro.lmk.debug Isso ativa os logs de depuração `lmkd`. Habilite a depuração durante o ajuste. false