Optimizadores de poca memoria

La plataforma de Android se basa en la premisa de que la memoria disponible es memoria desperdiciada, Android intenta usar toda la memoria disponible en todo momento. Por ejemplo, el sistema guarda las apps en la memoria después de que se cierran para que el usuario pueda volver a abrirlas con rapidez. Por esta razón, a menudo, los dispositivos Android funcionan con muy poca memoria libre (consulta la asignación de memoria de Android aquí).

El proceso del daemon del optimizador de poca memoria (LMK) de Android supervisa el estado de la memoria de un sistema Android en ejecución y reacciona a la alta presión de la memoria cerrando los procesos menos esenciales para que el sistema funcione a niveles aceptables.

Para decidir qué proceso debe cerrar, el daemon de LMK utiliza una puntuación de memoria insuficiente llamada oom_adj_score para priorizar los procesos en ejecución. Primero se cierran los procesos con una puntuación alta. Primero se cierran las apps en segundo plano y, por último, los procesos del sistema. En la siguiente tabla, se enumeran las categorías de puntuación de LMK en orden descendente. Primero se cierran los procesos de la categoría de mayor puntuación, que se encuentran en la fila uno:

Procesos de Android clasificados de mayor a menor puntuación: Apps en segundo plano, app anterior, app de la página principal, servicios, apps perceptibles, app en primer plano, persistente, sistema y nativa.
Figura 1: Procesos de Android, con puntuaciones altas en la parte superior y bajas en la parte inferior.

Herramientas de generación de perfiles de memoria

Las siguientes herramientas pueden ayudarte a encontrar y diagnosticar problemas de memoria de las siguientes maneras:

  • Observa el modo en que tu app asigna memoria en el tiempo. Puedes encontrar un gráfico en tiempo real de la cantidad de memoria que usa tu app, la cantidad de objetos Java asignados y cuándo se produce la recolección de elementos no utilizados.
  • Inicia eventos de recolección de elementos no utilizados y toma una instantánea del montón de Java mientras se ejecuta tu app.
  • Registra las asignaciones de memoria de tu app, inspecciona todos los objetos asignados y observa el seguimiento de la pila para cada asignación.

Si tu juego se ejecuta en un motor nativo, usa HWAddress Sanitizer para depurar la asignación de memoria nativa.

Generador de perfiles de memoria de Android Studio

Android Studio proporciona el Generador de perfiles de memoria como componente de Android Profiler, que te ayuda a identificar fugas de memoria y saturación de la memoria que pueden provocar inestabilidades, fallas e incluso bloqueos de apps. El generador de perfiles muestra un gráfico en tiempo real del uso de memoria de tu app y te permite capturar un volcado de montón, forzar la recolección de elementos no utilizados y realizar el seguimiento de la asignación de memoria.

Figura 2: Visualización de referencias globales de JNI en el Generador de perfiles de memoria de Android Studio.

Herramientas de generación de perfiles de memoria de Unity

Si usas Unity Engine para compilar tus apps, puedes seguir la guía de generación de perfiles de memoria de Unity. Unity ofrece dos herramientas para analizar el uso de memoria en tu aplicación en Unity.

El primero es el módulo Generador de perfiles de memoria, un generador de perfiles integrado que te brinda información básica sobre dónde usa memoria tu aplicación.

El módulo de memoria muestra las asignaciones de memoria, como la memoria de texturas y la memoria de malla.
Figura 3: Ventana del Generador de perfiles de Unity con el módulo Memory seleccionado.

La segunda herramienta es el paquete Generador de perfiles de memoria, que es un paquete de Unity que puedes agregar a tu proyecto. El paquete agrega una ventana adicional del Generador de perfiles de memoria al editor de Unity. El Generador de perfiles de memoria te permite analizar el uso de memoria en tu aplicación con aún más detalle. Puedes almacenar y comparar instantáneas para encontrar pérdidas de memoria o ver el diseño de la memoria para encontrar problemas de fragmentación de la memoria.

Figura 4: Análisis de una instantánea de memoria con la ventana del Generador de perfiles de memoria.

Unreal Memory Insights

Las apps creadas con Unreal Engine pueden usar Unreal Memory Insights para ver información detallada sobre la asignación y la desasignación de memoria, incluidas las etiquetas de memoria de bajo nivel (LLM) y las pilas de llamadas asociadas con los bloques de memoria.

El sistema de consultas de Memory Insights puede encontrar asignaciones activas en cualquier momento, identificar cambios en el uso de la memoria, ubicar fugas de memoria y diferenciar las asignaciones a corto plazo de las de largo plazo.

A partir de UE 5.4, Memory Insights admite el registro de memoria con pilas de llamadas para proyectos de Android.

El registro de Estadísticas de memoria muestra el gráfico de memoria principal, el recuento de asignación en vivo y el recuento de eventos de asignación/liberación.
Figura 5: Es el dispositivo de rastreo de Memory Insights de Unreal.

Estadísticas de memoria baja

Android proporciona devoluciones de llamada y APIs que te permiten reducir los requisitos de memoria de tu juego y determinar por qué se finalizaron las ejecuciones anteriores del juego.

Devoluciones de llamada

No te registres para recibir devoluciones de llamada de trim en desuso. Android no tiene ninguna API para detectar eventos nativos de presión de memoria cuando el sistema alcanza los límites de memoria. Las devoluciones de llamada de recorte no fueron útiles para evitar la finalización por falta de memoria, por lo que Android las dejó todas en desuso, excepto TRIM_MEMORY_UI_HIDDEN y TRIM_MEMORY_BACKGROUND.

Finalización del juego

Android intenta usar toda la memoria disponible para almacenar en caché las apps y los juegos, y así garantizar que se carguen rápidamente (lo que mejora la experiencia del usuario). Sin embargo, cuando la memoria se limita, el sistema cierra las apps y los juegos que consumen más memoria para liberar espacio y permitir el funcionamiento normal del dispositivo.

La información, las estadísticas y las prácticas recomendadas para ayudarte a lograr un mejor uso de la memoria del juego incluyen lo siguiente:

  • Usa ApplicationExitInfo: Esta API devuelve el motivo por el que el sistema Android detuvo la ejecución anterior del juego. Usa ApplicationExitInfo para verificar si la poca memoria fue la causa de una finalización de ejecución de un proceso anterior. Verifica si el juego se cerró debido a la poca memoria para que se pueda optimizar y usar menos memoria en ese dispositivo.
  • Consulta la RAM física total: Para evitar que se cierre el juego cuando está en primer plano y para que coincida con las capacidades del dispositivo, consulta la RAM física total por dispositivo para obtener una granularidad precisa y ajustar el uso de memoria del juego en función de eso. Si el objetivo es evitar que las apps se cierren poco después de pasar a segundo plano (para permitir que el jugador realice varias tareas a la vez), usa las devoluciones de llamada de recorte (específicamente TRIM_MEMORY_UI_HIDDEN) para reducir el uso de memoria del juego.

Recursos adicionales