Cómo administrar de manera eficaz la memoria en juegos

En la plataforma de Android, el sistema intenta usar tanta cantidad de memoria del sistema (RAM) como sea posible y realiza varias optimizaciones de memoria para liberar espacio cuando es necesario. Estas optimizaciones pueden tener un efecto negativo en tu juego: puede ralentizarlo o detenerlo por completo. Puedes obtener más información sobre estas optimizaciones en el tema Asignación de memoria entre procesos.

En esta página, se explican los pasos que puedes seguir a fin de evitar condiciones de poca memoria que afecten tu juego.

Responde a onTrimMemory()

El sistema usa onTrimMemory() para notificar a tu app sobre eventos de ciclo de vida que representen una buena oportunidad para que tu reduje voluntariamente su uso de memoria y evite que el optimizador de poca memoria (LMK) para liberar memoria para que usen otras apps.

Si la app se cierra en segundo plano, la próxima vez que se inicie el usuario tu app, experimentarán una demora inicio en frío Aplicaciones que reducen su es menos probable que se elimine el uso de memoria cuando pasa a segundo plano. en segundo plano.

Cuando se responde a eventos de recorte, es mejor liberar asignaciones de memoria grandes que no se necesitan de inmediato y que podrían reconstruirse según la demanda. Para Por ejemplo, si tu app tiene una caché de mapas de bits que se decodificaron de forma local imágenes comprimidas almacenadas, es a menudo una buena idea cortar o purgar esta en caché en respuesta 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.
            }
        }
    }
}

C#

using UnityEngine;
using System.Collections;
using System.Collections.Generic;

class LowMemoryTrigger : MonoBehaviour
{
    private void Start()
    {
        Application.lowMemory += OnLowMemory;
    }
    private void OnLowMemory()
    {
        // Respond to low memory condition (e.g., Resources.UnloadUnusedAssets())
    }
}

Cómo usar la versión beta de la API de Memory Advice

La API de Memory Advice se desarrolló como un alternativa a onTrimMemory, que tiene una recuperación y precisión mucho más altas en la predicción de LMK inminentes. La API lo consigue estimando la cantidad de de memoria que están en uso y luego notificar a la app cuando se cumplen se superan los umbrales. La API también puede informar el porcentaje estimado de el uso de la memoria directamente en tu app. Puedes usar la API de Memory Advice como alternativa a onTrimMemory para la administración de la memoria.

Para usar la API de Memory Advice, consulta la guía de introducción.

Sé conservador con los presupuestos de memoria

Invierte la memoria de forma conservadora con el fin de evitar que esta se agote. Los siguientes son algunos elementos que debes tener en cuenta:

  • Tamaño de la memoria RAM física: Los juegos a menudo usan entre ¼ y ½ de la cantidad física de RAM en el dispositivo.
  • Tamaño máximo de zRAM: Una mayor zRAM significa que el juego puede tener más memoria para asignar. Esta cantidad puede variar según el dispositivo. Busca SwapTotal en /proc/meminfo para conocer este valor.
  • Uso de memoria del SO: Los dispositivos que designan más RAM a los procesos del sistema dejan menos memoria para tu juego. El sistema detiene el proceso de tu juego antes de finalizar sus procesos.
  • Uso de memoria de las apps instaladas: Prueba tu juego en dispositivos que tengan instaladas muchas apps. Las apps de redes sociales y chat deben ejecutarse de forma constante y afectar la cantidad de memoria libre.

Si no puedes comprometerte con un presupuesto de memoria conservador, adopta un enfoque más flexible. Si el sistema tiene problemas de memoria baja, reduce la cantidad de memoria que usa el juego. Por ejemplo, asigna texturas de menor resolución o almacena menos sombreadores en respuesta a onTrimMemory(). Este enfoque dinámico relativo a la asignación de memoria requiere más trabajo de parte del desarrollador, en especial durante la fase de diseño del juego.

Evita la hiperpaginación

La hiperpaginación ocurre cuando la memoria libre es baja, pero no lo suficiente para detener el juego. En esta situación, kswapd tendrá páginas recuperadas que el juego aún necesita, por lo que intentará volver a cargarlas desde la memoria. Como no hay suficiente espacio, las páginas se seguirán reemplazando (reemplazo continuo). El registro del sistema informará esta situación como un subproceso en el que kswapd se ejecuta de manera continua.

Un síntoma de la hiperpaginación es la latencia prolongada de fotogramas (quizás un segundo o más). Para resolver esta situación, reduce la huella de memoria del juego.

Usa las herramientas disponibles

Android cuenta con una colección de herramientas que ayudan a comprender la forma en que el sistema administra la memoria.

Meminfo

Esta herramienta recopila estadísticas de memoria a fin de mostrar qué cantidad de memoria PSS se asignó y las categorías para las que se usó.

Imprime las estadísticas de meminfo de una de las siguientes maneras:

  • Usa el comando adb shell dumpsys meminfo package-name:
  • Usa la llamada MemoryInfo de la API de Android Debug.

La estadística PrivateDirty muestra la cantidad de memoria RAM dentro del proceso que no se puede paginar en el disco y que no se comparte con ningún otro proceso. La mayor parte de esta cantidad quedará disponible para el sistema cuando se detenga ese proceso.

Puntos de seguimiento de memoria

Los puntos de seguimiento de memoria hacen un seguimiento de la cantidad de memoria RSS que usa tu juego. El cálculo del uso de memoria RSS es mucho más rápido que el del uso de PSS. Debido a que es más rápido calcularlo, RSS muestra un nivel de detalle mayor de los cambios en el tamaño de la memoria a fin de obtener mediciones más precisas del uso máximo de memoria. Por lo tanto, resulta más fácil advertir los máximos que podrían hacer que el juego se quede sin memoria.

Perfetto y los registros largos

Perfetto es un paquete de herramientas para recopilar información de rendimiento y memoria en un dispositivo y mostrarla en una IU basada en la Web. Admite registros arbitrariamente largos, por lo que puedes ver cómo el RSS cambia con el tiempo. También puedes emitir búsquedas de SQL sobre los datos que produce para su procesamiento sin conexión. Habilita los registros largos desde la app de Registro del sistema. Asegúrate de que la categoría memory:Memory esté habilitada para el registro.

heapprofd

heapprofd es una herramienta de seguimiento de memoria que forma parte de Perfetto. Esta herramienta puede ayudarte a encontrar fugas de memoria, ya que muestra dónde se asignó la memoria por medio de malloc. heapprofd puede iniciarse con una secuencia de comandos de Python y, dado que la herramienta tiene una sobrecarga baja, no afecta el rendimiento como lo hacen otras herramientas como Malloc Debug.

bugreport

bugreport es una herramienta de registro cuyo fin es descubrir si tu juego falló o no por quedarse sin memoria. El resultado de la herramienta es mucho más detallado que si usaras logcat. Resulta útil para la depuración de memoria, ya que muestra si el juego falló porque se quedó sin memoria o si el LMK lo detuvo.

Para obtener más información, consulta Cómo capturar y leer informes de errores.