Los mapas de bits suelen ser los objetos que más memoria consumen en una app. Las operaciones de decodificación y escalamiento suelen estar en la ruta crítica para la renderización de fotogramas. Optimizar el uso de memoria de mapa de bits proporciona mejoras significativas en la capacidad de respuesta de la IU, la duración de la batería y la estabilidad general, ya que reduce los bloqueos, los ANR y las finalizaciones de procesos relacionados con OOM.
Identifica el uso elevado de memoria de mapa de bits
Android vitals proporciona métricas sobre el espacio en memoria de mapa de bits de una app mediante la agregación de datos de dispositivos Android. Estas métricas incluyen percentiles basados en períodos (por ejemplo, 28 días) por paquete y proceso. Estos datos ayudan a identificar tendencias y posibles regresiones en la eficiencia de la memoria en diferentes tipos y versiones de dispositivos.
Android vitals comparte el uso de memoria de mapa de bits de tu app desglosado por los siguientes estados de proceso:
- Primer plano: El proceso de la app es visible. Se espera que el percentil 99 sea significativamente más alto en primer plano que en otros estados de proceso, pero los desarrolladores deben investigar si la relación P99/P50 es significativa (p.ej., superior a 3.5 veces), ya que esto suele indicar una fuga de memoria de mapa de bits. Para identificar esto, busca una divergencia entre el uso típico (P50) y el uso atípico (P99). Si bien la expansión general de recursos aumenta la memoria de manera uniforme en todos los percentiles, las fugas de memoria se acumulan con el tiempo, lo que sesga en gran medida los datos del extremo final (P99). Asegúrate de que las asignaciones de mapa de bits en primer plano no persistan innecesariamente después de que la app pase a otros estados.
- Servicios percibidos por el usuario: El proceso de la app se ejecuta en un estado perceptible. Esto incluye servicios en primer plano, tareas aceleradas y tareas de transferencia de datos iniciadas por el usuario. Las apps no deben retener asignaciones de mapa de bits en primer plano pesadas cuando pasan a estos estados. Debido a que estos servicios están diseñados para tareas de larga duración, retener recursos grandes degrada la experiencia general del usuario y obliga al daemon Low Memory Killer (LMKD) a recuperar memoria mediante la finalización de procesos de menor prioridad.
- Segundo plano: La app ejecuta un servicio en segundo plano o se ejecutó recientemente en segundo plano, pero aún no se almacenó en caché. Debido a que este estado de proceso es menos importante que los procesos en primer plano o perceptibles, las apps deben liberar explícitamente recursos de mapa de bits grandes aquí para reducir la presión de la memoria.
- Almacenado en caché: La app está en estado almacenado en caché. Este estado es muy sensible a la presión de la memoria del sistema, como los LMK. Las apps deben reducir de forma proactiva el uso de memoria de mapa de bits en este estado para evitar la expulsión por parte del SO.
Factores que contribuyen al uso elevado de memoria de mapa de bits
La memoria virtual que nunca se usó también puede incluirse en el cálculo. Si ves un uso de memoria de mapa de bits inesperadamente alto, verifica que no estés asignando memoria que no se use.
Recursos
Analiza mapas de bits en Android Studio
Generación de perfiles de Android Studio para mapas de bits
Usa el Generador de perfiles de memoria para inspeccionar las asignaciones de memoria en tiempo real, capturar volcados de montón y analizar objetos en busca de fugas de memoria. Además, usa el analizador de montón para detectar fugas de memoria, identificar asignaciones de mapa de bits duplicadas y visualizar la retención de objetos.
Detección automática de fugas con LeakCanary
Integra la biblioteca LeakCanary para automatizar la detección de fugas de memoria en tu app. LeakCanary proporciona un análisis automático del montón, identifica objetos que deberían haberse recolectado como elementos no utilizados, pero que aún se conservan en la memoria, como los mapas de bits retenidos por actividades o fragmentos destruidos.
Documentación sobre el rendimiento de mapas de bits
Estos recursos proporcionan orientación integral sobre las prácticas recomendadas para el control eficiente de mapas de bits en diferentes componentes de Android.
- Cómo administrar la memoria del mapa de bits
- Cómo optimizar imágenes de mapa de bits
- Administra la memoria de tu app
Lista de tareas para desarrolladores para optimizar el uso de memoria de mapa de bits
Para optimizar la eficiencia de la memoria de mapa de bits, sigue los tres principios básicos: reducir, reutilizar y reciclar.
- Reducir: Minimiza el espacio en memoria inicial cuando cargas o muestras mapas de bits.
- Reutilizar: Implementa mecanismos de almacenamiento en caché para evitar asignaciones de mapa de bits redundantes.
- Reciclar: Libera recursos de forma proactiva para permitir la reasignación de memoria para procesos activos.
La siguiente lista de tareas para desarrolladores puede ayudarte a optimizar el uso de memoria de mapa de bits.
| Principio básico | Área | Descripción |
|---|---|---|
| Reducir | Elimina mapas de bits duplicados | Analiza los volcados de montón con el Generador de perfiles de memoria para detectar asignaciones de mapa de bits redundantes. Consulta la guía Cómo administrar la memoria del mapa de bits. |
| Aprovecha las bibliotecas de carga de imágenes | Usa bibliotecas como Glide y Coil para automatizar el subprocesamiento, el almacenamiento en caché y la decodificación eficiente. | |
| Implementa la reducción de muestreo | Decodifica imágenes para que coincidan con las dimensiones del contenedor de la IU de destino en lugar de cargar recursos de resolución completa. | |
| Usa RGB_565 para imágenes opacas | Reduce el espacio en memoria en un 50% cambiando de ARGB_8888 a una configuración de 16 bits para imágenes sin transparencia. |
|
| Prioriza VectorDrawables | Usa vectores para íconos y gráficos básicos para garantizar un escalamiento nítido con una sobrecarga de memoria mínima. | |
| Optimiza la entrega de imágenes del servidor | Configura las APIs de backend para entregar imágenes adaptadas a la densidad del dispositivo y las dimensiones de ImageView. | |
| Elimina los márgenes transparentes | Evita asignar memoria para píxeles "invisibles" usando InsetDrawable o el padding de diseño en lugar de márgenes integrados. Consulta Cómo diseñar apps para Android con un rendimiento de memoria óptimo. | |
| Reutilización | Configura tamaños de caché óptimos | Adapta los límites de caché de memoria y disco según la RAM del dispositivo y la resolución de la pantalla. Consulta Cómo almacenar mapas de bits en caché. |
| Reciclaje | Borra recursos en segundo plano | Implementa TRIM_MEMORY_BACKGROUND para borrar cachés y mejorar la supervivencia de los procesos durante la presión de la memoria del sistema. |
| Libera recursos cuando la IU está oculta | Usa TRIM_MEMORY_UI_HIDDEN para liberar cachés de mapa de bits cuando la app ya no sea visible para el usuario. |
|
| Supervisa las fugas de memoria | Usa LeakCanary y el Generador de perfiles de memoria para encontrar mapas de bits retenidos después de que se destruye su LifecycleOwner. Consulta Administra la memoria de tu app. |