Daemon assassino de 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 a pressão da memória

Um sistema Android executando vários processos em paralelo pode encontrar situações em que a memória do sistema está esgotada e os processos que exigem mais memória sofrem atrasos perceptíveis. 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 em cache não críticos e assim por diante.

Historicamente, o Android monitorava a pressão de memória do sistema usando um driver LMK (in-kernel low memory killer), um mecanismo rígido que depende de valores codificados. A partir do kernel 4.12, o driver LMK é removido do kernel upstream e o userspace 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 bloqueio de pressão do kernel (PSI) para detecção de pressão de memória. O conjunto de patches PSI no kernel upstream (backported para 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 da 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 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 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 , tornando os monitores PSI o mecanismo padrão de detecção de pressão de memória para lmkd . Como os monitores PSI requerem suporte ao kernel, o kernel deve incluir os patches de backport do PSI e ser compilado com o suporte PSI ativado ( CONFIG_PSI=y ).

Desvantagens do driver LMK no kernel

O Android suspende o uso do driver LMK devido a vários problemas, incluindo:

  • Dispositivos com pouca RAM precisavam ser ajustados agressivamente e, mesmo assim, teriam um desempenho ruim em cargas de trabalho com grande cache de página ativo com suporte de arquivo. O fraco desempenho resultou em surra e sem mortes.
  • O driver do kernel LMK dependia de limites de memória livre, sem dimensionamento com base na pressão da memória.
  • Devido à rigidez do design, os parceiros geralmente personalizavam o driver para que funcionasse em seus dispositivos.
  • O driver LMK foi conectado à API do slab shrinker, que não foi projetada para operações pesadas, como pesquisar alvos e eliminá-los, o que retardou o processo vmscan .

Userspace lmkd

O userspace lmkd implementa a mesma funcionalidade que o driver in-kernel, mas usa os mecanismos existentes do kernel para detectar e estimar a pressão da memória. Esses mecanismos incluem o uso de eventos vmpressure gerados pelo kernel ou monitores de informações de parada de pressão (PSI) para obter notificações sobre os 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 a cada processo com base na importância do processo.

Usando userspace lmkd no Android 10

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

CONFIG_ANDROID_LOW_MEMORY_KILLER=n
CONFIG_MEMCG=y
CONFIG_MEMCG_SWAP=y

Matar estratégias

lmkd oferece suporte a estratégias de eliminação com base 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 de baixa memória e de alto desempenho:

  • Em dispositivos com pouca memória, o sistema deve 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 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 .

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

Configurando o lmkd

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

Propriedade Usar Padrão
ro.config.low_ram Especifique se o dispositivo é de baixa 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 processo (ou seja, corresponder à funcionalidade do driver LMK no kernel). false
ro.lmk.low A pontuação mínima de oom_adj para processos qualificados para serem eliminados no nível vmpressure baixo. 1001
(Desativado)
ro.lmk.medium A pontuação mínima de oom_adj para processos qualificados para serem eliminados no nível médio de vmpressure . 800
(serviços em cache ou não essenciais)
ro.lmk.critical A pontuação mínima oom_adj para processos qualificados para serem eliminados no nível crítico de vmpressure . 0
(qualquer processo)
ro.lmk.critical_upgrade Habilite a atualização para o nível crítico. false
ro.lmk.upgrade_pressure A mem_pressure máxima na qual o nível é atualizado porque o sistema está trocando muito. 100
(Desativado)
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
(Desativado)
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á feita. 0
(Desativado)
ro.lmk.debug Ative 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

Userspace lmkd no Android 11

O Android 11 melhora o lmkd introduzindo uma nova estratégia de matança. 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 é responsável por níveis de uso de recursos de memória e thrashing para evitar a falta de memória e a degradação do desempenho. Essa estratégia de eliminação substitui as estratégias anteriores e pode ser usada em dispositivos de alto desempenho e baixa RAM (Android Go).

Requisitos do kernel

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

  • Inclua patches PSI e ative o PSI (backports disponíveis nos kernels comuns do Android 4.9, 4.14 e 4.19).
  • Inclua patches de suporte a 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 o lmkd no Android 11

A estratégia de eliminação de memória no Android 11 é compatível com os botões de ajuste e os padrões listados abaixo. Esses recursos funcionam em dispositivos de alto desempenho e baixa RAM.

Propriedade Usar Padrão
Alta performance RAM baixa
ro.lmk.psi_partial_stall_ms O limite de parada 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 muito tarde, diminua esse valor para acionar notificações anteriores. 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 travamento de PSI, em milissegundos, para acionar notificações de memória crítica. Se o dispositivo receber notificações de pressão de memória crítica muito tarde, diminua esse valor para acionar notificações anteriores. Se as notificações de pressão de memória crítica forem acionadas desnecessariamente, aumente esse valor para tornar o dispositivo menos sensível ao ruído. 700
ro.lmk.thrashing_limit A quantidade máxima de redefinições do conjunto de trabalho como uma porcentagem do tamanho total do cache de página com suporte de arquivo. As redefinições do conjunto de trabalho acima desse valor significam que o sistema é considerado thrashing em seu 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 interrompido desnecessariamente por motivos de thrashing, aumente o valor para permitir mais thrashing. 100 30
ro.lmk.thrashing_limit_decay O decaimento do limite de thrashing expresso 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 o thrashing contínuo produzir mortes desnecessárias, diminua o valor. Se a resposta ao thrashing contínuo após um kill 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 cresce acima desse 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 intercambiáveis ​​estão gerando pressão de memória que não pode ser aliviada pela troca porque a maior parte da memória intercambiável já foi trocada. O valor padrão é 100, o que efetivamente desativa 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 troca livre como uma porcentagem do espaço total de troca. `lmkd` usa este valor como um limite para quando considerar o sistema como com falta de espaço de troca. Se o `lmkd` matar enquanto houver muito espaço na troca, diminua a porcentagem. Se kills `lmkd` acontecerem muito tarde, permitindo que kills OOM aconteçam, aumente a porcentagem. 20 10
ro.lmk.debug Isso habilita os logs de depuração `lmkd`. Ative a depuração durante o ajuste. false