Daemon de gerenciamento de memória

O Android 17 e versões mais recentes são compatíveis com o daemon de gerenciamento de memória (mmd), um daemon do sistema que lida com a configuração do daemon, os ajustes e as tarefas contínuas de troca ou manutenção do ZRAM.

Contexto

Antes da introdução do mmd, as configurações de ZRAM do Android eram fragmentadas e ofereciam personalização limitada. O mmd resolve isso centralizando o gerenciamento do ZRAM, permitindo uma lógica de configuração mais sofisticada e simplificando a adição de novos recursos e melhorias arquitetônicas. O mmd também estabelece uma separação clara de responsabilidades entre o processo system_server baseado em Java e a troca ou o gerenciamento de memória no nível do kernel.

Arquitetura e gerenciamento de ZRAM

Quando a inicialização é concluída (ou seja, quando sys.boot_completed=1), o mmd_setup tenta configurar o ZRAM com os parâmetros especificados. Depois que a configuração do ZRAM for concluída, o sistema vai ativar o serviço mmd, que lida com tarefas de manutenção contínuas.

Com o projeto mmd, as operações de manutenção são iniciadas em system_server enviando solicitações do Binder para mmd usando a interface IMmd. O mmd processa as tarefas de manutenção de execução de writeback de ZRAM, recompressão e writeback por processo com base no próprio mecanismo de política interna. O agendamento de ActivityManagerService e as políticas de manutenção do ZRAM podem ser configurados usando propriedades do sistema.

Integração do servidor do sistema (system_server)

O processo system_server baseado em Java determina quando mmd é invocado. O processo separa as limpezas de manutenção globais das otimizações de memória específicas por app.

Manutenção normal de pós-processamento

A manutenção global do ZRAM é feita pelo ActivityManagerService usando com.android.server.memory.ZramMaintenance.

zram-maintenance

Figura 1. Fluxo de programação de manutenção do ZRAM.

  • Mecanismo de programação:ZramMaintenance registra um trabalho periódico em segundo plano com o JobScheduler do Android.
  • Restrições de job:para evitar renderização lenta na interface do usuário em primeiro plano ou disputa de CPU, o job é configurado explicitamente com setRequiresDeviceIdle(true) e setRequiresBatteryNotLow(true).
  • Acionamento do binder:quando o programador dispara onStartJob(), system_server invoca mmd.doZramMaintenanceAsync(). Essa é uma chamada assíncrona do Binder unidirecional. O system_server não bloqueia a espera pela conclusão das varreduras de manutenção. O mmd coloca isso em uma linha de execução de worker em segundo plano para realizar a recompressão e o writeback sequencialmente.

Writeback por processo

A remoção direcionada de memória por processo é gerenciada pelo ActivityManagerService usando com.android.server.am.CachedAppOptimizer.

mmd-writeback

Figura 2: fluxo de gravação de retorno por processo do mmd.

Quando um processo passa para um estado armazenado em cache em segundo plano, o ActivityManager realiza a compactação da memória. Se um encerramento por falta de memória do processo for visível para o usuário, ou seja, o processo hospeda uma atividade, e se o writeback por processo do ZRAM reduzir o consumo de memória do processo a quase zero, o sistema vai seguir estas etapas:

  1. Após a compactação, CachedAppOptimizer envia uma mensagem atrasada (ZRAM_WRITEBACK_MSG) ao gerenciador de compactação interna (atrasada em mZramWritebackWaitSeconds).
  2. Quando o atraso expira, o ActivityManager abre um descritor de arquivo de processo seguro pidfd.
  3. O servidor do sistema chama mmd.asyncWritebackProcessZramMemory(pfd, callback).
  4. mmd executa o ioctl de writeback por processo e gera relatórios usando IMmdProcessWritebackCallback. Se for bem-sucedido, o ActivityManager vai sinalizar o registro do processo (setIsZramWrittenBack(app, true)) para aumentar o oom_score_adj do processo e registrar métricas em FrameworkStatsLog.ZRAM_WRITEBACK_EVENT.

Pré-busca por processo

Quando um usuário reinicia um app armazenado em cache anteriormente (descongelado devido a UNFREEZE_REASON_ACTIVITY), o ActivityManager minimiza a latência de inicialização do app causada por falhas de página importantes do armazenamento de apoio:

  1. CachedAppOptimizer intercepta o evento de descongelamento e invoca prefetchZram(app).
  2. O servidor do sistema envia o pidfd do app pelo Binder usando mmd.asyncPrefetchProcessZramMemory(pfd). O mmd emite o ioctl ZRAM_ANDROID_IOC_PROCESS_PREFETCH, instruindo o kernel a fazer a pré-busca assíncrona das páginas trocadas de volta para a RAM enquanto a linha de execução principal da interface do app está sendo inicializada.

Visão geral das tarefas de manutenção e pós-processamento

Esta seção descreve as operações de manutenção em segundo plano e as tarefas de pós-processamento que o mmd executa para otimizar o espaço de troca e a memória do sistema.

Manutenção no mmd

Em mmd, manutenção se refere a varreduras de manutenção programadas em segundo plano que otimizam o uso do espaço de troca e da memória física sem afetar o desempenho em primeiro plano do usuário ativo. Em vez de realizar varreduras contínuas e síncronas (que causariam ativações graves da CPU e instabilidade da interface), a manutenção é feita de forma assíncrona:

  1. O system_server dispara periodicamente doZramMaintenanceAsync() no Binder.

  2. O mmd coloca a solicitação em uma fila de trabalho em segundo plano LowPrioWorkItem::ZramMaintenance.

  3. Há uma única linha de execução de worker em mmd que gerencia uma fila de alta prioridade e uma de baixa prioridade. Os itens de trabalho de alta prioridade (como pré-busca por processo) são processados primeiro e podem forçar a interrupção de itens de trabalho de baixa prioridade. A manutenção e o writeback por processo funcionam como itens de trabalho de baixa prioridade. Quando removida, a linha de execução de worker executa duas operações principais de manutenção em sequência:

    • Recompressão ZRAM:verifica as páginas de troca atuais e recomprime as páginas inativas usando um algoritmo de compressão secundária de proporção mais alta, por exemplo, zstd.

    • Writeback da ZRAM:verifica páginas inativas e as remove completamente da RAM para o armazenamento flash de apoio, um dispositivo de loop de um arquivo em /data.

Tarefas de pós-processamento na zRAM

No módulo ZRAM do kernel do Linux e na arquitetura mmd, as tarefas de pós-processamento são as transformações assíncronas aplicadas às páginas de memória depois que elas já foram trocadas pelos caminhos de recuperação padrão do kernel (kswapd ou compactação).

Quando uma página é substituída inicialmente, o sistema prioriza a velocidade: ele usa um algoritmo de compactação primário rápido (como lz4) e armazena a página compactada na RAM. No entanto, com o tempo, muitas páginas trocadas ficam inativas ou ociosas, por exemplo, apps em cache em segundo plano que não são retomados por horas. Deixar páginas frias na zRAM rápida e levemente compactada é ineficiente.

Pipeline de pós-processamento

O mmd implementa um ciclo de vida de pós-processamento de vários estágios para otimizar essas páginas:

mmd-page-lifecycle

Figura 3. mmd ciclo de vida da página.

  1. Etapa 1: troca inicial (compressão rápida): a memória é recuperada primeiro pelo kswapd ou pela compactação de apps. Normalmente, essa primeira recuperação é realizada usando um algoritmo de compactação rápida, como lz4, e o conteúdo é armazenado na RAM.

  2. Etapa 2: marcação de inatividade (envelhecimento e rastreamento): mmd acessos de rastreamento de inatividade, rastreamento de memória do kernel (CONFIG_ZRAM_TRACK_ENTRY_ACTIME) ou usa o marcador de inatividade do software para rastrear por quanto tempo as páginas ficaram sem interação.

  3. Etapa 3: pós-processamento 1: recompressão (recuperação na memória): as páginas que atingem a idade de inatividade da recompressão (min_idle_seconds a max_idle_seconds) passam por recompressão. O mmd grava em /sys/block/zram0/recompress para instruir o kernel a descompactar a página lz4 e compactá-la novamente usando zstd. Isso recupera a RAM física sem causar desgaste de gravação flash.

  4. Etapa 4: pós-processamento 2: gravação de volta (remoção para armazenamento flash): se a pressão na memória continuar e as páginas atingirem a idade de inatividade de gravação de volta (normalmente 20 horas ou mais), o mmd vai acionar a gravação de volta. O mmd grava em /sys/block/zram0/idle e /sys/block/zram0/writeback para desalojar a página compactada completamente da RAM para o armazenamento flash de apoio.

Configuração da ZRAM

O mmd carrega e processa as seguintes propriedades de configuração do ZRAM:

Propriedade Usar Padrão
mmd.zram.enabled Se a configuração do mmd ZRAM está ativada. false
mmd.zram.num_devices O número de dispositivos ZRAM a serem configurados. Para um número N, os dispositivos zram0 a zram<N-1> precisam estar presentes antes que o sistema defina sys.boot_completed=1. As propriedades na lista de dispositivos por ZRAM podem ser configuradas por dispositivo. 1
mmd.zram.device_priority Valores de prioridade a serem transmitidos ao chamar swapon. Não definido
mmd.zram.comp_algorithm Algoritmo de compactação ZRAM. O algoritmo de compactação padrão do kernel será usado se não for especificado. Não definido
mmd.zram.size Tamanho do dispositivo zRAM em bytes ou uma porcentagem do tamanho da RAM do dispositivo, por exemplo, 75%. 50%
mmd.zram.writeback.enabled Define se o writeback do ZRAM será ativado. false
mmd.zram.writeback.device_size O tamanho do dispositivo de gravação em bytes ou a porcentagem da partição de dados. O tamanho real do dispositivo pode ser ajustado com base no espaço disponível na partição de dados. 1073741824 (1 GiB)
mmd.zram.writeback.min_free_space_mib Espaço livre mínimo em MiB que precisa estar disponível após a configuração do dispositivo de writeback. 1536 (1,5 GiB)
mmd.zram.writeback.use_nr_tags_prop Quando true, usa o valor em mmd.zram.writeback.nr_tags para configurar a profundidade da fila do dispositivo de loop que faz o writeback do ZRAM. Essa é uma solução alternativa para situações em que a política do SELinux do fornecedor não pode ser configurada para permitir que mmd leia diretamente nr_tags do dispositivo de bloco que faz backup de /data. false
mmd.zram.writeback.nr_tags Consulte mmd.zram.writeback.use_nr_tags_prop. Não definido
mmd.zram.recompression.enabled Se o recurso de recompressão ZRAM deve ser ativado. false
mmd.zram.recompression.algorithm Algoritmo secundário de recompressão do ZRAM. zstd

Propriedades do dispositivo por ZRAM

Quando mmd.zram.num_devices é maior que um, propriedades específicas podem ser configuradas opcionalmente em cada dispositivo ZRAM definindo a propriedade como um valor separado por vírgulas que contém exatamente mmd.zram.num_devices elementos. Essas propriedades incluem:

  • mmd.zram.size
  • mmd.zram.comp_algorithm
  • mmd.zram.device_priority
  • mmd.zram.recompression.enabled
  • mmd.zram.recompression.huge_idle.enabled
  • mmd.zram.recompression.idle.enabled
  • mmd.zram.recompression.huge.enabled
  • mmd.zram.recompression.threshold_bytes
  • mmd.zram.recompression.algorithm
  • mmd.zram.writeback.device_size
  • mmd.zram.writeback.huge_idle.enabled
  • mmd.zram.writeback.idle.enabled
  • mmd.zram.writeback.huge.enabled

Descontinuação da configuração atual do ZRAM

Embora swapon_all ainda esteja disponível no Android para configurar a ZRAM e o espaço de troca baseado em disco, mmd é a abordagem preferida para o gerenciamento da ZRAM, facilitando a configuração e recursos avançados, como a recompactação da ZRAM.

Quando a configuração de ZRAM mmd é ativada por mmd.zram.enabled:

  • A configuração do ZRAM na implementação do swapon_all se torna uma operação nula.
  • As configurações atuais do ZRAM, como config_zramWriteback no arquivo de sobreposição config.xml e as propriedades do sistema de writeback ro.zram.*, são ignoradas.

Ajustes de manutenção do ZRAM

A manutenção do ZRAM funciona sem precisar de configuração, e você pode ajustar ainda mais usando as propriedades do sistema nesta seção.

Programação de manutenção do ZRAM

Essas propriedades controlam como e quando as tarefas de manutenção do ZRAM são programadas pelo system_server.

Propriedade Usar Padrão
mm.zram.maintenance.first_delay_seconds O atraso antes do início da primeira manutenção do ZRAM. 3600 (1 hora)
mm.zram.maintenance.periodic_delay_seconds O atraso entre o agendamento de manutenção subsequente do ZRAM. 3600 (1 hora)
mm.zram.maintenance.require_device_idle Se a manutenção do ZRAM só deve ser iniciada quando o dispositivo estiver inativo. true
mm.zram.maintenance.require_battery_not_low Se é necessário que a bateria não esteja fraca antes de iniciar a manutenção do ZRAM. true

Política de writeback do ZRAM

Os parâmetros a seguir controlam quando e qual tipo de memória é gravado no dispositivo de suporte:

Propriedade Usar Padrão
mmd.zram.writeback.backoff_seconds O tempo de espera desde a última operação de gravação. 600 (10 minutos)
mmd.zram.writeback.min_idle_seconds Combinado com mmd.zram.writeback.max_idle_seconds para calcular a idade de inatividade de uma página para que ela se qualifique para gravação com base na fração de utilização da memória. A idade ociosa calculada é interpolada exponencialmente entre os dois parâmetros para minimizar o trabalho sem pressão de memória. 72000 (20 horas)
mmd.zram.writeback.max_idle_seconds Número máximo de segundos usados para calcular a idade da página inativa de forma dinâmica com base na utilização da memória. 90000 (25 horas)
mmd.zram.writeback.huge.enabled Define se o writeback da página HUGE será ativado. false
mmd.zram.writeback.idle.enabled Define se o writeback da página IDLE será ativado. true
mmd.zram.writeback.huge_idle.enabled Define se o writeback da página HUGE_IDLE será ativado. true
mmd.zram.writeback.min_bytes Número mínimo de bytes a serem gravados em uma rodada de gravação ociosa. 5242880 (5 MiB)
mmd.zram.writeback.max_bytes Número máximo de bytes a serem gravados em uma rodada de gravação inativa. 314572800 (300 MiB)
mmd.zram.writeback.max_bytes_per_day Número máximo de bytes a serem gravados em um período de 24 horas. 25769803776 (24 GiB)
mmd.zram.writeback.limit.enabled Define se a contabilização do limite de orçamento de gravação diária será ativada. true

Política de recompressão do ZRAM

Os parâmetros a seguir controlam quando e qual tipo de memória é recompactado:

Propriedade Usar Padrão
mmd.zram.recompression.backoff_seconds O tempo de espera desde a última recompressão. 1800 (30 minutos)
mmd.zram.recompression.min_idle_seconds Combinado com mmd.zram.recompression.max_idle_seconds para calcular a idade de inatividade de uma página e determinar se ela está qualificada para recompressão com base na fração de utilização da memória. A idade ociosa calculada é interpolada exponencialmente entre os dois parâmetros para minimizar o trabalho sem pressão de memória. 7200 (2 horas)
mmd.zram.recompression.max_idle_seconds Número máximo de segundos usados para calcular dinamicamente a idade da página inativa. 14400 (4 horas)
mmd.zram.recompression.threshold_bytes Tamanho mínimo em bytes das páginas ZRAM consideradas para recompressão. 1024 (1 KiB)
mmd.zram.recompression.huge.enabled Se a recompactação da página HUGE precisa ser ativada. true
mmd.zram.recompression.idle.enabled Se a recompactação da página IDLE precisa ser ativada. true
mmd.zram.recompression.huge_idle.enabled Se a recompactação da página HUGE_IDLE precisa ser ativada. true

Rastreamento de páginas inativas da zRAM

mmd A manutenção da zRAM marca as páginas como inativas com base no tempo decorrido desde o último acesso. Esse recurso exige que as configurações de kernel CONFIG_ZRAM_TRACK_ENTRY_ACTIME ou CONFIG_ZRAM_MEMORY_TRACKING estejam ativadas. CONFIG_ZRAM_TRACK_ENTRY_ACTIME é ativado por padrão nos kernels do GKI 6.18 e mais recentes. Em kernels anteriores, ele tem sobrecarga de memória e não é ativado por padrão.

Se a configuração do kernel não estiver ativada, a manutenção da mmd ZRAM vai usar uma lógica de substituição de software para rastrear páginas inativas da ZRAM:

  1. Marque todas as páginas da zRAM como inativas quando o mmd for iniciado.

  2. Pule as próximas manutenções do ZRAM até que o período de espera necessário tenha passado.

  3. Retorno de gravação da zRAM ou recompilação de páginas inativas. Se houver páginas inativas restantes devido a limites de gravação, o mmd continuará gravando páginas na próxima manutenção sem marcar novas páginas como inativas (pulando a etapa 4).

  4. Se todas as páginas inativas forem gravadas novamente, marque todas as páginas da ZRAM como inativas de novo e volte para a etapa 2. Se o writeback da ZRAM estiver desativado, o mmd vai marcar todas as páginas da ZRAM como inativas quando a recompactação da ZRAM acontecer após a duração de inatividade da recompactação.

Orientações para solução de problemas e validação

Siga as etapas de validação e os procedimentos de solução de problemas abaixo para verificar e diagnosticar operações de mmd e ZRAM.

Validar a configuração do ZRAM

Para verificar se mmd configurou o ZRAM com sucesso durante a inicialização:

  1. Verifique o algoritmo de compactação ativo e o tamanho do disco:

    cat /sys/block/zram0/comp_algorithm
    cat /sys/block/zram0/disksize
    
  2. Verifique as propriedades do sistema mmd e o estado do serviço em execução:

    getprop | grep mmd.zram
    dumpsys -l | grep mmd
    

Validar a manutenção e o writeback do ZRAM

Verifique se as tarefas de manutenção de writeback e recompressão do ZRAM estão funcionando:

  1. Verifique o status do dispositivo de bloco de suporte:

    cat /sys/block/zram0/bd_stat
    
  2. Monitore /sys/block/zram0/mm_stat para verificar a eficiência da recompressão. As mudanças nos tamanhos dos dados compactados vão aparecer após os ciclos de manutenção.

Validar o writeback por processo

O seguinte pode ser usado para validar se o writeback por processo está funcionando:

  • Verifique adb logcat -s mmd para ver registros de gravação bem-sucedidos ou diagnósticos de falha.

Problemas comuns e diagnósticos

Estas são situações de erro comuns que o usuário pode encontrar:

  • WritebackDailyLimitExceeded:esse erro indica que a cota de mmd.zram.writeback.max_bytes_per_day foi atingida. Quando isso acontece, o mmd pausa o writeback inativo até que a janela de 24 horas avance.
  • Process prefetch or writeback failed:esse erro pode ser observado no logcat quando um ioctl falha. Algumas causas comuns:
    • EBADF ou ESRCH: o processo de destino foi encerrado antes que mmd pudesse enviar o pidfd ao kernel.
    • ENOSPC: a partição de armazenamento de suporte está cheia ou a fila do dispositivo de loop está esgotada.
  • ZRAM não configurada:se o mmd não conseguir configurar a ZRAM na inicialização, talvez seja porque scripts de inicialização legados do swapon_all ou do fornecedor bloquearam o /dev/block/zram0 antes que o mmd pudesse ser executado.