Como verificar o uso da memória com as ferramentas do Unity

No sistema Android, o limite de memória para o Memory Limiter (Android 17 e mais recentes) e o valor de referência para o Android vitals no Google Play Console é 'RSS anônimo + troca'. Esse valor representa o nível de pressão da memória física realmente ocupado pelo processo e é uma métrica essencial que precisa ser monitorada para uma operação estável do app.

Atualmente, é difícil medir o uso da memória que corresponda exatamente a "RSS anônimo + troca" no tempo de execução ou estaticamente no Unity Engine.

Para resolver esse problema, esta página apresenta como rastrear o valor de 'RSS anônimo + troca' com alta confiabilidade por aproximação usando o Unity Profiler, a API ProfileRecorder e o Unity Memory Profiler em um ambiente do Unity Engine.

Verificar o uso da memória no tempo de execução

No Unity, medir diretamente o uso de memória "RSS anônimo + troca" exato do Android no tempo de execução sem sobrecarga pode ser desafiador. No entanto, é possível estimar esse valor (com uma variação de aproximadamente 10%) usando as APIs do Profiler integradas do Unity.

Método 1: usar o Profiler

É possível estimar o uso da memória total somando os valores retornados pelas seguintes APIs do Profiler:

using UnityEngine;
using UnityEngine.Profiling;

public class MemoryMonitor : MonoBehaviour
{
    public long GetEstimatedMemoryUsageBytes()
    {
        long totalReserved = Profiler.GetTotalReservedMemoryLong();
        long monoHeapSize = Profiler.GetMonoHeapSizeLong();

        return totalReserved + monoHeapSize;
    }
}

Método 2: usar a classe ProfilerRecorder

É possível rastrear as métricas Total Reserved Memory e Gfx Reserved Memory usando o ProfilerRecorder:

  • Em builds de desenvolvimento: calcule 'Total Reserved Memory' - 'Gfx Reserved Memory'.

  • Em builds de lançamento: use 'Total Reserved Memory' diretamente.

using Unity.Profiling;
using UnityEngine;

public class MemoryMonitor : MonoBehaviour
{
    ProfilerRecorder totalRecorder;

#if DEVELOPMENT_BUILD
    ProfilerRecorder gfxRecorder;
#endif

    private void OnEnable()
    {
        totalRecorder = ProfilerRecorder.StartNew(ProfilerCategory.Memory, "Total Reserved Memory");

#if DEVELOPMENT_BUILD
        gfxRecorder = ProfilerRecorder.StartNew(ProfilerCategory.Memory, "Gfx Reserved Memory");
#endif
    }

    private void OnDisable()
    {
        totalRecorder.Dispose();

#if DEVELOPMENT_BUILD
        gfxRecorder.Dispose();
#endif
    }

    public long GetEstimatedMemoryUsageBytes()
    {
#if DEVELOPMENT_BUILD
        if (totalRecorder.Valid && gfxRecorder.Valid)
        {
            return totalRecorder.LastValue - gfxRecorder.LastValue;
        }
#else
        if (totalRecorder.Valid)
        {
            return totalRecorder.LastValue;
        }
#endif
        return 0;
    }
}

Limitação:

  • As alocações de memória que ignoram o gerenciador de memória do Unity (por exemplo, NativeMalloc(IntPtr size)) não podem ser rastreadas por essas APIs.

  • Essas APIs podem não ser compatíveis, dependendo da versão do Unity.

Analisar a distribuição de memória (análise estática)

Se for detectado um uso elevado de memória no tempo de execução, será necessário identificar onde a memória está sendo consumida. A análise da distribuição de memória permite eliminar alocações desnecessárias e reduzir a ocupação geral de memória do jogo.

Unity Memory Profiler

Para realizar uma análise detalhada da memória e otimizar seu jogo, use o pacote Unity Memory Profiler. Para localizar os itens correspondentes ao uso de 'RSS anônimo + troca' do SO Android:

  1. Capture um snapshot usando o Unity Memory Profiler.
  2. Abra o snapshot e navegue até All of Memory > Resident Memory on Device.
  3. Calcule a soma dos seguintes itens:

    • Untracked
    • Android Runtime
    • Nativo
    • Gerenciado
    Métricas de memória visíveis quando definidas como "Memória residente" no Unity Memory Profiler
    Figura 1. As descrições de memória são armazenadas na memória residente

A soma total serve como um substituto prático para 'RSS anônimo + troca' do SO Android, oferecendo insights acionáveis para a análise de memória do jogo.

Limitação:

  • Sob forte pressão de memória, o SO Android pode compactar ou trocar páginas de memória ativas para liberar RAM. Como o Unity Memory Profiler não pode rastrear a memória trocada, podem surgir discrepâncias durante cenários de uso da memória elevado.

  • Esses recursos podem ser limitados, dependendo da versão do Unity.

Avaliação mais precisa

Para verificar os valores exatos de 'RSS anônimo + troca' do SO Android, use Perfetto. Ele permite medir o uso da memória preciso no nível do sistema e analisar detalhadamente o consumo de memória do jogo.