Daemon guardião da memória do processo

O Android 17 e versões mais recentes oferecem suporte ao daemon guardião de memória de processo (PMGD, na sigla em inglês), que protege a integridade do sistema e a experiência do usuário gerenciando proativamente o uso da memória por processo. O daemon melhora a estabilidade geral do dispositivo aplicando limites de memória de maneira adequada em processos de destino específicos, verificando se vazamentos ou picos de memória isolados não causam degradação no desempenho de todo o sistema.

Enquanto os eliminadores globais convencionais de pouca memória agem apenas quando todo o sistema está sob pressão, o PMGD adota uma abordagem granular. O daemon faz isso monitorando os valores de memória do grupo de controle v2 dos processos de destino. Quando um processo segmentado excede os limites de memória configurados, o pmgd processa as violações de limite registrando átomos de memória do Statsd antes de encerrar o processo.

Como funciona

O daemon usa inotify para detectar eventos de pressão de memória (especificamente atividade de uso intenso de memória usando memory.events). Quando um processo monitorado aciona um evento de memória, pmgd realiza as seguintes ações:

  1. Verificação anônima de memória:avalia a memória anônima do processo. Se exceder o anon_limit_in_mb configurado, o pmgd vai encerrar o processo imediatamente.
  2. Período de espera de recuperação:se a memória anônima estiver abaixo do limite especificado, o pmgd aguardará um período de carência de recuperação do sistema (reclaim_wait_time_secs).
  3. Avaliação da memória após a recuperação:se o memory.current do processo de destino permanecer maior ou igual a memory.high após o período de carência, ou se a memória anônima exceder anon_limit_in_mb, pmgd vai encerrar o processo imediatamente.

Isso é feito continuamente até que o processo seja encerrado ou a recuperação no processo reduza o uso da memória abaixo dos limites de memória especificados.

Recursos de saúde do sistema

  • Limitação de taxa de reinicialização:para evitar loops de inicialização ou falhas persistentes, o pmgd rastreia a interrupção de processos em /data/misc/pmgd/history.json. O daemon restringe os processos a uma única interrupção iniciada por pmgd por reinicialização do dispositivo.

Configuração do SELinux

A capacidade do PMGD de monitorar processos é restrita pela política do SELinux. Se você configurar o PMGD para monitorar um processo cujo domínio não é permitido pela política, como um processo do sistema específico do fornecedor, o PMGD não poderá monitorá-lo, e você poderá ver negações do SELinux no logcat.

Para permitir que o PMGD monitore processos em domínios adicionais, você deve estender as permissões do PMGD atualizando a política do SELinux específica do dispositivo para o PMGD.

A seguir, um exemplo de arquivo device/<vendor>/<device>/sepolicy/pmgd.te que adiciona acesso a um novo domínio:

# Allow pmgd to access vendor_system_apps
r_dir_file(pmgd, vendor_system_apps)

Para mais informações sobre como escrever uma política específica do dispositivo, consulte Implementar o SELinux.

Configuração definida pelo fornecedor

A configuração do PMGD é orientada pelo fornecedor e configurada por um arquivo JSON obrigatório /vendor/etc/pmgd/config.json. Isso lista os processos a serem rastreados, o perfil de limite de memória configurado (usando perfis de tarefas do cgroup) e o limite de memória anônima fixa em megabytes.

Campos de configuração do fornecedor

A configuração JSON fornecida é uma lista de processos e limites, definidos pelos seguintes campos:

Campo Tipo Obrigatório Descrição Padrão
target_cmd String Sim O nome do comando do processo de destino a ser monitorado, por exemplo, system_server. N/A
uid Número inteiro Não O ID de usuário (UID) do processo. Se omitido, pmgd aplica a regra globalmente a qualquer processo que corresponda a target_cmd. N/A
reclaim_wait_time_secs Número inteiro Não O período de carência em segundos para aguardar que o sistema recupere a memória antes de avaliar o limite novamente. 5
mem_limit_profile String Sim O nome do perfil de tarefa do cgroup que define "memory.high". Isso é usado para definir o limite de memória do processo. N/A
anon_limit_in_mb Número inteiro Sim O limite máximo de memória anônima em megabytes. Se a utilização de memória anônima ultrapassar esse valor, o pmgd vai encerrar o processo imediatamente. N/A
additional_task_profiles Lista de strings Não Uma lista de outros perfis de tarefa a que pmgd se aplica ao processo quando o monitoramento é iniciado. Lista vazia

Confira a seguir um exemplo de configuração do perfil de tarefa do cgroup em vendor/etc/task_profiles.json:

{
  "Attributes": [
    ...
    {
      "Name": "MemHigh",
      "Controller": "memory",
      "File": "memory.high"
    }
  ],
  "Profiles": [
    {
      "Name": "SystemServerMemoryHighLimit",
      "Actions": [
        {
          "Name": "SetAttribute",
          "Params":
          {
            "Name": "MemHigh",
            "Value": "1080M"
          }
        }
      ]
    }
  ]
}

Confira a seguir um exemplo de configuração do PMGD em vendor/etc/pmgd/config.json:

{
  "targets": [
    {
      "target_cmd": "system_server",
      "uid": 1000,
      "reclaim_wait_time_secs": 5,
      "mem_limit_profile": "SystemServerMemoryHighLimit",
      "anon_limit_in_mb": 300
    }
  ]
}