Les bitmaps sont souvent les objets qui consomment le plus de mémoire dans une application. Les opérations de décodage et de mise à l'échelle se trouvent fréquemment sur le chemin critique du rendu des frames. L'optimisation de l'utilisation de la mémoire bitmap améliore considérablement la réactivité de l'interface utilisateur, l'autonomie de la batterie et la stabilité globale en réduisant les à-coups, les ANR et les arrêts de processus liés à une erreur de mémoire insuffisante.
Identifier une utilisation élevée de la mémoire bitmap
Android Vitals fournit des métriques sur l'espace mémoire utilisé par les bitmaps d'une application en agrégeant les données des appareils Android. Ces métriques incluent des centiles basés sur une période (par exemple, 28 jours) par package et par processus. Ces données permettent d'identifier les tendances et les régressions potentielles en termes d'efficacité de la mémoire sur différents types et versions d'appareils.
Android Vitals partage l'utilisation de la mémoire bitmap de votre application, répartie selon les états de processus suivants :
- Premier plan : le processus de l'application est visible. Il est normal que le P99 soit beaucoup plus élevé au premier plan que dans d'autres états de processus, mais les développeurs doivent examiner si le rapport P99/P50 est important (par exemple, supérieur à 3,5x), car cela indique souvent une fuite de mémoire bitmap. Pour identifier ce problème, recherchez une divergence entre l'utilisation typique (P50) et l'utilisation aberrante (P99). En effet, alors que le gonflement général des éléments augmente la mémoire de manière uniforme sur tous les centiles, les fuites de mémoire s'aggravent au fil du temps, ce qui fausse considérablement les données de fin de queue (P99). Assurez-vous que les allocations de bitmap au premier plan ne persistent pas inutilement après que l'application passe à d'autres états.
- Services perçus par l'utilisateur : le processus de l'application s'exécute dans un état perceptible. Cela inclut les services de premier plan, les tâches accélérées et les tâches de transfert de données déclenchées par l'utilisateur. Les applications ne doivent pas conserver d'allocations de bitmap au premier plan importantes lors du passage à ces états. Étant donné que ces services sont conçus pour les tâches de longue durée, la conservation d'éléments volumineux dégrade l'expérience utilisateur globale et force le démon Low Memory Killer (LMKD) à récupérer de la mémoire en mettant fin aux processus de priorité inférieure.
- Arrière-plan : l'application exécute un service d'arrière-plan ou a récemment été mise en arrière-plan, mais n'est pas encore mise en cache. Étant donné que cet état de processus est moins important que les processus au premier plan ou perceptibles, les applications doivent libérer explicitement les éléments bitmap volumineux ici pour réduire la pression sur la mémoire.
- Mise en cache : l'application est dans un état mis en cache. Cet état est très sensible à la pression sur la mémoire système, comme les LMK. Les applications doivent réduire de manière proactive l'utilisation de la mémoire bitmap dans cet état pour éviter l'éviction par le système d'exploitation.
Facteurs contribuant à une utilisation élevée de la mémoire bitmap
La mémoire virtuelle qui n'a jamais été utilisée peut également être incluse dans le calcul. Si vous constatez une utilisation de la mémoire bitmap anormalement élevée, vérifiez que vous n'allouez pas de mémoire inutilisée.
Ressources
Analyser les bitmaps dans Android Studio
Profilage des bitmaps dans Android Studio
Utilisez le Profileur de mémoire pour inspecter les allocations de mémoire en temps réel, capturer les empreintes de la mémoire et analyser les objets pour détecter les fuites de mémoire. Utilisez également l'analyseur de tas pour détecter les fuites de mémoire, identifier les allocations de bitmap en double et visualiser la conservation des objets.
Détection automatique des fuites avec LeakCanary
Intégrez la bibliothèque LeakCanary pour automatiser la détection des fuites de mémoire dans votre application. LeakCanary fournit une analyse automatique du tas, en identifiant les objets qui auraient dû être collectés, mais qui sont toujours conservés en mémoire, tels que les bitmaps conservés par les activités ou les fragments détruits.
Documentation sur les performances des bitmaps
Ces ressources fournissent des conseils complets sur les bonnes pratiques pour une gestion efficace des bitmaps dans différents composants Android.
Check-list pour les développeurs afin d'optimiser l'utilisation de la mémoire bitmap
Pour optimiser l'efficacité de la mémoire bitmap, suivez les trois principes fondamentaux : réduire, réutiliser et recycler.
- Réduire : minimisez l'espace mémoire utilisé initial lors du chargement ou de l'affichage des bitmaps.
- Réutiliser : implémentez des mécanismes de mise en cache pour éviter les allocations de bitmap redondantes.
- Recycler : libérez de manière proactive les ressources pour permettre la réallocation de mémoire pour les processus actifs.
La check-list suivante pour les développeurs peut vous aider à optimiser l'utilisation de la mémoire bitmap.
| Principe fondamental | Région | Description |
|---|---|---|
| Limiter | Éliminer les bitmaps en double | Analysez les empreintes de la mémoire à l'aide du Profileur de mémoire pour détecter les allocations de bitmap redondantes. Consultez le guide Gérer la mémoire bitmap. |
| Exploiter les bibliothèques de chargement d'images | Utilisez des bibliothèques telles que Glide et Coil pour automatiser le threading, la mise en cache et le décodage efficace. | |
| Implémenter le sous-échantillonnage | Décodez les images pour qu'elles correspondent aux dimensions du conteneur d'interface utilisateur cible au lieu de charger des éléments en pleine résolution. | |
| Utiliser RGB_565 pour les images opaques | Réduisez l'espace mémoire utilisé de 50% en passant de ARGB_8888 à une configuration 16 bits pour les images sans transparence. |
|
| Prioriser les VectorDrawables | Utilisez des vecteurs pour les icônes et les graphiques de base afin de garantir une mise à l'échelle nette avec une surcharge de mémoire minimale. | |
| Optimiser l'affichage des images côté serveur | Configurez les API de backend pour diffuser des images adaptées à la densité de l'appareil et aux dimensions de l'ImageView. | |
| Éliminer les marges transparentes | Évitez d'allouer de la mémoire pour les pixels "invisibles" en utilisant InsetDrawable ou un remplissage de mise en page au lieu de marges intégrées. Consultez la section Concevoir des applications Android performantes en termes de mémoire. | |
| Réutiliser | Configurer des tailles de cache optimales | Adaptez les limites de mémoire et de cache du disque en fonction de la RAM de l'appareil et de la résolution de l'écran. Consultez la section Mise en cache des bitmaps. |
| Recycler | Supprimer les ressources en arrière-plan | Implémentez TRIM_MEMORY_BACKGROUND pour effacer les caches et améliorer la survie des processus en cas de pression sur la mémoire système. |
| Libérer les éléments lorsque l'interface utilisateur est masquée | Utilisez TRIM_MEMORY_UI_HIDDEN pour libérer les caches bitmap lorsque l'application n'est plus visible par l'utilisateur. |
|
| Surveiller les fuites de mémoire | Utilisez LeakCanary et le Profileur de mémoire pour trouver les bitmaps conservés après la destruction de leur LifecycleOwner. Consultez la section Gérer la mémoire de votre application. |