Na plataforma Android, o sistema tenta usar o máximo de memória do sistema (RAM, na sigla em inglês) possível e executa várias otimizações de memória para liberar espaço quando necessário. Essas otimizações podem ter um efeito negativo no jogo, na lentidão ou à disposição total. Saiba mais sobre essas otimizações no tópico Alocação de memória entre processos.
Para garantir a estabilidade do dispositivo, a partir do Android 17 (nível 37 da API), o sistema começa a aplicar limites de memória do app com base na RAM total do dispositivo. Se um app exceder esses limites, o Android vai encerrar o processo sem um stack trace associado.
Esta página explica as etapas que você pode seguir para evitar que condições de pouca memória afetem seu jogo.
Responda ao onTrimMemory()
O sistema usa
onTrimMemory()
para notificar seu app sobre eventos de ciclo de vida que apresentam uma boa oportunidade para que seu
app reduza voluntariamente o uso da memória e evite ser encerrado pelo
LMK
para liberar memória para outros apps.
Se o app for encerrado em segundo plano, na próxima vez que o usuário iniciar o app, ele vai passar por uma inicialização a frio lenta . É menos provável que os apps que reduzem o uso da memória ao passar para o segundo plano sejam encerrados.
Ao responder a eventos de corte, é melhor liberar grandes alocações de memória que não são necessárias imediatamente e podem ser reconstruídas sob demanda. Por
exemplo, se o app tiver um cache de bitmaps decodificados de imagens compactadas armazenadas localmente, geralmente é uma boa ideia cortar ou limpar este
cache em resposta a
TRIM_MEMORY_UI_HIDDEN.
Kotlin
class MainActivity : AppCompatActivity(), ComponentCallbacks2 { override fun onTrimMemory(level: Int) { if (level >= ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) { // Release memory related to UI elements, such as bitmap caches. } if (level >= ComponentCallbacks2.TRIM_MEMORY_BACKGROUND) { // Release memory related to background processing, such as by // closing a database connection. } } }
Java
public class MainActivity extends AppCompatActivity implements ComponentCallbacks2 { public void onTrimMemory(int level) { switch (level) { if (level >= ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) { // Release memory related to UI elements, such as bitmap caches. } if (level >= ComponentCallbacks2.TRIM_MEMORY_BACKGROUND) { // Release memory related to background processing, such as by // closing a database connection. } } } }
Conservar a capacidade da memória
Gerencie a memória de maneira conservadora para evitar a falta de memória. Veja alguns itens a serem considerados:
- Tamanho da RAM física: os jogos geralmente usam entre ¼ e ½ do valor da RAM física no dispositivo.
- Tamanho máximo da zRAM: mais zRAM significa que o jogo pode ter mais memória para alocar. Esse valor pode variar de acordo com o dispositivo. Procure
SwapTotalem/proc/meminfopara encontrar esse valor. - Uso da memória do SO: os dispositivos que designam mais RAM para os processos do sistema deixam menos memória para o jogo. O sistema encerra o processo do jogo antes de encerrar processos do sistema.
- Uso de memória dos apps instalados: teste seu jogo em dispositivos que têm muitos apps instalados. Os apps de redes sociais e chat precisam ser executados constantemente e afetar a quantidade de memória livre.
Se não for possível usar uma capacidade de memória conservadora, tente uma abordagem mais flexível. Se o sistema tiver problemas de pouca memória, reduza a quantidade de memória que o jogo está usando. Por exemplo, aloque texturas de baixa resolução ou armazene menos sombreadores em resposta a onTrimMemory(). Essa abordagem dinâmica para a alocação de memória requer mais trabalho do desenvolvedor, especialmente na fase de design do jogo.
Evite a sobrecarga
A sobrecarga ocorre quando a memória livre é baixa, mas não o suficiente para encerrar o jogo.
Nessa situação, kswapd recuperou páginas de que o jogo ainda precisa, por isso, tenta recarregar as páginas da memória. Não há espaço suficiente, então as páginas continuam sendo trocadas (troca contínua).
O rastreamento do sistema informa essa situação como uma linha de execução em que kswapd é executado continuamente.
Um sintoma de sobrecarga é um tempo longo para a renderização do frame, possivelmente um segundo ou mais. Reduza o consumo de memória do jogo para resolver essa situação.
Use as ferramentas disponíveis
O Android tem uma coleção de ferramentas que ajudam a entender como o sistema gerencia a memória.
Meminfo
Essa ferramenta coleta estatísticas sobre a memória para mostrar quanta memória PSS foi alocada e as categorias para as quais ela foi usada.
Veja as estatísticas do meminfo de uma das seguintes maneiras:
- Use o comando
adb shell dumpsys meminfo package-name; - Use a chamada
MemoryInfoda API Android Debug.
A estatística PrivateDirty mostra a
quantidade de RAM dentro do processo que não pode ser paginada no disco e não é compartilhada
com outros processos. A maior parte desse valor fica disponível para o sistema quando esse processo é encerrado.
Tracepoints de memória
Os tracepoints de memória rastreiam a quantidade de memória RSS que seu jogo está usando. Calcular o uso de memória RSS é muito mais rápido do que calcular o uso do PSS. Como é mais rápido de calcular, o RSS mostra uma granularidade mais refinada nas alterações no tamanho da memória para medições mais precisas do uso de memória de pico. Portanto, é mais fácil observar picos que possam fazer com que o jogo fique sem memória.
Perfetto e rastreamentos longos
O Perfetto (link em inglês) é um pacote de ferramentas para coletar informações de desempenho e memória de um dispositivo e exibi-lo em uma IU baseada na Web. É compatível com rastreamentos arbitrariamente longos para que você possa visualizar como o RSS muda ao longo do tempo. Também é possível emitir consultas SQL dos dados produzidos para processamento off-line. Ative os rastreamentos longos no app Rastreamento do sistema. Verifique se a categoria memory:Memory está ativada para o rastreamento. Para instrumentação de memória personalizada no desenvolvimento e teste, também é possível usar a API (Beta)heapprofd.
Heapprofd
heapprofd é uma ferramenta de rastreamento de memória que faz parte do Perfetto. Essa ferramenta pode ajudar a encontrar vazamentos de memória ao mostrar onde a memória foi alocada usando malloc. O heapprofd pode ser iniciado usando um script Python. Como a ferramenta tem baixa sobrecarga, isso não afeta o desempenho como outras ferramentas, como a Malloc Debug.
Relatório de bugs
bugreport é uma ferramenta de geração de registros para descobrir se o jogo falhou porque ficou sem memória. A saída da ferramenta é muito mais detalhada do que a do logcat. Ele é útil para depuração de memória porque mostra se o jogo falhou por falta de memória ou se foi encerrado pelo LMK.
Para mais informações, consulte Capturar e ler relatórios de bugs.