Cómo verificar el uso de memoria con las herramientas de Unity

En el sistema Android, el umbral de límite de memoria para el limitador de memoria (Android 17+) y el valor de referencia para la métrica vital de memoria en Google Play Console es 'RSS anónimo + intercambio'. Este valor representa el nivel de presión de la memoria física que ocupa el proceso y es una métrica fundamental que se debe supervisar para que la app funcione de forma estable.

Actualmente, es difícil medir el uso de memoria que coincida exactamente con "RSS anónimo + intercambio" en el tiempo de ejecución o de forma estática dentro de Unity Engine.

Para abordar este problema, en esta página, se explica cómo hacer un seguimiento del valor "RSS anónimo + intercambio" con alta confiabilidad a través de la aproximación con Unity Profiler, la API de ProfileRecorder y Unity Memory Profiler en un entorno de Unity Engine.

Verifica el uso de memoria en el tiempo de ejecución

En Unity, medir directamente el uso exacto de memoria 'RSS anónimo + intercambio' en el tiempo de ejecución sin sobrecarga puede ser un desafío. Sin embargo, puedes estimar este valor de cerca (con una variación de aproximadamente el 10%) con las APIs de Profiler integradas de Unity.

Método 1: Usa el generador de perfiles

Para estimar el uso total de memoria, suma los valores que muestran las siguientes APIs de 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: Usa la clase ProfilerRecorder

Puedes hacer un seguimiento de las métricas Total Reserved Memory y Gfx Reserved Memory con ProfilerRecorder:

  • En las compilaciones de desarrollo, calcula 'Total Reserved Memory' - 'Gfx Reserved Memory'.

  • En las compilaciones de lanzamiento, usa 'Total Reserved Memory' directamente.

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;
    }
}

Limitación:

  • Estas APIs no pueden hacer un seguimiento de las asignaciones de memoria que omiten el administrador de memoria de Unity (p.ej., NativeMalloc(IntPtr size)).

  • Es posible que estas APIs no sean compatibles según tu versión de Unity.

Analiza el desglose de la memoria (análisis estático)

Si se detecta un uso elevado de memoria en el tiempo de ejecución, debes identificar dónde se consume la memoria. Analizar la distribución de la memoria te permite eliminar las asignaciones innecesarias y reducir el espacio en memoria general del juego.

Generador de perfiles de memoria de Unity

Para realizar un análisis de memoria detallado y optimizar tu juego, usa el paquete Generador de perfiles de memoria de Unity. Para ubicar los elementos correspondientes al uso de 'RSS anónimo + intercambio' del SO Android, haz lo siguiente:

  1. Captura una instantánea con Unity Memory Profiler.
  2. Abre la instantánea y navega a All of Memory > Resident Memory on Device.
  3. Calcula la suma de los siguientes elementos:

    • Untracked
    • Android Runtime
    • Nativo
    • Administrado
    Métricas de memoria que se pueden ver cuando se establece en Memoria residente en el Generador de perfiles de memoria de Unity
    Figura 1. Las descripciones de la memoria se almacenan en la memoria residente.

La suma total sirve como un sustituto práctico para 'RSS anónimo + intercambio' del SO Android, ya que proporciona estadísticas prácticas para el análisis de la memoria del juego.

Limitación:

  • Bajo una fuerte presión de memoria, el SO Android puede comprimir o intercambiar páginas de memoria activas para liberar memoria RAM. Debido a que Unity Memory Profiler no puede hacer un seguimiento de la memoria intercambiada, pueden surgir discrepancias durante las situaciones de uso elevado de memoria.

  • Estas funciones pueden estar limitadas según tu versión de Unity.

Evaluación más precisa

Para verificar los valores exactos de 'RSS anónimo + intercambio' del SO Android, usa Perfetto. Te permite medir el uso preciso de la memoria a nivel del sistema y analizar minuciosamente el espacio de memoria de tu juego.