A memória é um recurso essencial e finito em dispositivos Android. Como desenvolvedor da plataforma Android ou OEM, entender como a memória funciona em todos os níveis, do ambiente de execução do Java ao kernel do Linux, é essencial para criar um sistema estável e de alto desempenho.
Este guia oferece uma visão geral abrangente da arquitetura de memória do Android, das ferramentas disponíveis para análise e de exercícios práticos para ajudar você a identificar e resolver problemas relacionados à memória.
Objetivos
Depois de concluir este guia, você vai conseguir:
- Explicar os conceitos fundamentais da memória do Android, incluindo o modelo de processo Zygote e os arquivos mapeados na memória.
- Diferenciar entre tamanho do conjunto residente (RSS), tamanho do conjunto proporcional (PSS) e tamanho do conjunto exclusivo (USS).
- Use ferramentas de linha de comando padrão, como
dumpsys meminfoeshowmap, para avaliar rapidamente o uso da memória. - Capture e analise heap dumps do Java usando o AHAT para encontrar vazamentos e alocações excessivas.
- Use o Perfetto e o
heapprofdpara analisar a memória Java e nativa em todo o sistema. - Entenda os indicadores de pressão de memória em todo o sistema, como as informações de pouca pressão (PSI, na sigla em inglês), e monitore a atividade do Low Memory Killer (LMK).
- Observe a atividade de recuperação no nível do kernel, incluindo a troca de ZRAM e a remoção do cache de páginas.
Estrutura do guia
Este guia está organizado nas seções a seguir, que devem ser lidas sequencialmente:
- Conceitos fundamentais: os princípios técnicos básicos da memória do Android.
- Ferramentas de avaliação rápida: use
meminfo,showmapeprocstatspara uma triagem rápida. - Análise da memória Java: Investigações detalhadas do heap do Java com o AHAT.
- Bitmaps e memória: entender como as imagens afetam a RAM e usar ferramentas para criar perfis delas.
- Análise de memória nativa: criação de perfil de memória C/C++ com
o Perfetto e o
heapprofd. - WebView e memória: entenda a arquitetura de vários processos e o consumo de memória de WebViews.
- O código do app é memória: entenda como o carregamento de classes e o dex bloat afetam a RAM.
- Linhas de execução e memória: análise do custo de pilhas de linhas de execução nativas.
- Localidade e desempenho da memória: entender como os padrões de acesso a dados afetam o desempenho da CPU.
- Vinculações de serviço e estados de processo: entenda como as dependências entre processos afetam as pontuações de OOM.
- Solução de problemas em todo o sistema: monitoramento de PSI, LMK, troca de ZRAM e remoção de cache de página.
- Recuperação de memória: remoção e troca: entenda o memcg,
a cobrança e a recuperação proativa com
memory.reclaim. - Interação entre kswapd e lmkd: entenda como o kswapd e o lmkd funcionam juntos sob pressão.
- Retornar páginas de memória ao SO: use
madviseeposix_fadvisepara retornar páginas de heap e de cache de arquivos não utilizadas ao kernel. - Manter o trabalho em segundo plano ativo com um processo enxuto: mover serviços e workers em segundo plano para um processo dedicado para que a memória de interface e gráficos não seja mantida em prioridade elevada.
Pré-requisitos e ambiente
Este guia apresenta fluxos de trabalho de referência, dados de comparativo de mercado e estudos de caso que demonstram como diagnosticar e resolver problemas de memória do Android.
- Ferramentas de análise: as técnicas neste guia usam principalmente ferramentas padrão
de desempenho do Android, incluindo Perfetto,
dumpsys meminfo,showmape AHAT. - Privilégios de raiz: alguns fluxos de trabalho de diagnóstico no nível do sistema, como
inspecionar a pressão de memória do kernel ou os contadores de PMU de hardware, exigem
privilégios de raiz elevados (
adb root) em um dispositivo userdebug ou build de emulador.
Comece aqui: conceitos fundamentais