L'optimisation de la mémoire est essentielle pour offrir des expériences de jeu stables et performantes sur Android. Ce guide explique pourquoi l'efficacité de la mémoire est importante, comment le système d'exploitation Android gère les limites de mémoire des processus et les nouvelles métriques de mémoire dans la Google Play Console pour vous aider à surveiller et à améliorer la qualité technique de votre jeu.
L'importance de l'optimisation de la mémoire
L'optimisation de la mémoire de votre jeu est essentielle pour fidéliser les joueurs, étendre la compatibilité des appareils et respecter les normes de qualité de la plate-forme :
- Prévention des démarrages à froid (expérience utilisateur et fidélisation) : lorsqu'un joueur quitte temporairement votre jeu (par exemple, pour répondre à une notification ou consulter un message), le système d'exploitation place le processus du jeu en arrière-plan. Si l'espace mémoire utilisé en arrière-plan du jeu est trop élevé, le Low Memory Killer (LMK) du système donne la priorité à l'arrêt du processus du jeu pour récupérer de la RAM pour les tâches de premier plan. La prochaine fois que l'utilisateur reprendra le jeu, au lieu d'une reprise à chaud fluide et instantanée, le jeu devra effectuer un long démarrage à froid, en rechargeant complètement les éléments graphiques lourds, l'audio et les binaires du moteur de jeu à partir du stockage. En maintenant une faible utilisation de la mémoire en arrière-plan, vous évitez ces arrêts silencieux en arrière-plan, vous préservez l'état de l'utilisateur et vous vous assurez que les joueurs peuvent reprendre leur session immédiatement. Pour en savoir plus sur le comportement du LMK du système, consultez le guide Android Vitals - Low memory killers.
- Stabilité de l'écosystème et des appareils : une utilisation inefficace de la mémoire et les fuites de mémoire dégradent l'état général du système. Lorsque la mémoire système est limitée, le système est soumis à une forte pression, ce qui entraîne une baisse de la fréquence d'images, des à-coups dans l'interface utilisateur et des problèmes audio. Si la pression sur la mémoire est trop forte, le Low Memory Killer (LMK) du système arrête de manière agressive les processus en arrière-plan, ce qui oblige les autres applications à subir des démarrages à froid lents et à perdre l'état de l'utilisateur lorsque les joueurs passent d'une tâche à l'autre.
- Arrêts au niveau de la plate-forme : à partir d'Android 17 (niveau d'API 37), le système est plus proactif dans l'arrêt des processus qui utilisent trop de mémoire. Si l'encombrement de votre jeu est trop élevé, l'OS peut arrêter son processus de manière abrupte sans générer de trace de la pile standard.
- Compatibilité des appareils : alors que les appareils phares disposent de 12 à 16 Go de RAM, une grande partie du public mondial de joueurs utilise des appareils avec 4 ou 6 Go de RAM. Une gestion appropriée de la mémoire garantit que votre jeu reste accessible et réactif sur tous les niveaux de matériel sans nécessiter de packages d'éléments complexes et distincts.
Comprendre la mémoire dans Android
Pour concevoir des stratégies efficaces de budgétisation de la mémoire, les développeurs doivent comprendre comment la plate-forme Android gère la mémoire physique et comment elle mesure l'encombrement actif de leur jeu.
Concepts de base de la mémoire Android
Pour connaître les concepts fondamentaux concernant la gestion de la mémoire au niveau de la plate-forme, consultez la documentation officielle Présentation de la gestion de la mémoire. Cette ressource couvre quatre domaines architecturaux :
- Présentation de la mémoire : Android utilise la pagination et la mise en correspondance de mémoire (mmap) pour gérer la RAM. Il ne prend pas en charge de fichier d'échange traditionnel sur disque. Au lieu de cela, il s'appuie sur la compression de pages (à l'aide de zRAM) et la récupération de pages pour libérer de la mémoire physique.
- Allocation de mémoire entre les processus : Android partage la RAM sur l'ensemble du système. Il attribue des tas de mémoire spécifiques pour l'exécution de la machine virtuelle Dalvik ou ART, tout en permettant aux environnements de développement natifs (tels que les moteurs de jeu C++) de demander de la mémoire au tas de mémoire du système natif.
- Gestion de la mémoire des applications : fonctionnant sous un modèle multiprocessus, Android s'attend à ce que les applications surveillent dynamiquement l'état de leur cycle de vie et libèrent volontairement les ressources inutiles (telles que les graphiques et les bitmaps non mis en cache) pour assurer le bon fonctionnement du système.
- Présentation des processus et des threads : le système catégorise les processus dans une hiérarchie en fonction de leur visibilité et de leur importance perçues par l'utilisateur, ce qui détermine les processus qui sont maintenus en vie et ceux qui sont arrêtés en premier en cas de mémoire insuffisante.
Métrique d'espace mémoire utilisé total
Le Memory Limiter Android 17 au niveau de la plate-forme évalue la consommation des processus à l'aide de l'encombrement total de la mémoire plutôt que de la taille résidente totale (RSS) ou de la taille de la mémoire virtuelle.
Encombrement total de la mémoire = RSS anonyme (RssAnon) + espace d'échange non compressé (VmSwap)
Pour éviter que les jeux ne dépassent les limites de la plate-forme, vous devez comprendre exactement ce que ces métriques représentent au niveau du système. Pour en savoir plus sur ces métriques, les allocations de RAM physique et la gestion des pages sauvegardées dans des fichiers, consultez la section Comprendre les métriques RSS et d'espace d'échange du guide Surveiller l'utilisation de la mémoire.
Contraintes de mémoire
Pour maintenir la stabilité du système et s'assurer que les applications ne consomment pas de ressources excessives, la plate-forme Android gère les limites de mémoire pour les processus en cours d'exécution.
Memory Limiter dans Android 17 et versions ultérieures
Android 17 (niveau d'API 37) et versions ultérieures gèrent des limites de mémoire strictes par application à l'aide de Linux cgroup v2 pour éviter que des applications individuelles ne provoquent une instabilité à l'échelle du système. Pour en savoir plus sur l'implémentation technique, consultez le guide AOSP Memory Limiter et l'article de blog Prioritizing Memory Efficiency: Essential Steps for Android 17.
- Mécanisme : le Memory Limiter surveille tous les processus d'application et
attribue dynamiquement des limites en fonction de l'état du cycle de vie du processus :
- Processus visibles (premier plan) : les processus d'application qui affichent actuellement une interface utilisateur sont censés exécuter un ensemble de travail de ressources plus important et bénéficient d'une limite plus généreuse.
- Processus non visibles (arrière-plan ou services) : les processus d'application qui effectuent un travail actif sans afficher d'interface utilisateur sont soumis à un budget plus strict et plus restrictif.
- Attributs du noyau : le service repose sur deux attributs principaux :
memory.high: limite souple. Lorsqu'elle est dépassée, le noyau limite le processus et tente de récupérer de la mémoire de manière agressive. Cette récupération peut entraîner une dégradation des performances du jeu.memory.swap.max: gère une limite stricte sur l'espace d'échange ou zRAM que le processus peut utiliser.
- Comportement d'arrêt : si un processus continue d'allouer de la mémoire anonyme
au-delà de
memory.highet épuise sa capacité d'échange, les allocations échouent et le système d'exploitation arrête le processus en mode silencieux. Cet arrêt est enregistré à l'aide deApplicationExitInfosous le motif de sortie Memory Limiter (disponible à partir d'Android 17, 26Q4).
Nouvelles limites de mémoire dans Play Console Vitals
Pour aider les développeurs à identifier de manière proactive les problèmes de mémoire, Google Play introduit de nouvelles métriques dans Play Console Android Vitals. Play Console suit le 90e centile (P90) de l'espace mémoire utilisé RSS anonyme + espace d'échange de vos sessions de jeu pour identifier les valeurs aberrantes extrêmes.
Les seuils d'avertissement et de mesure d'application sont ajustés en fonction de la capacité de RAM physique et des états des processus de l'appareil. Ces limites s'appliquent en deux phases distinctes.
Pour obtenir des consignes détaillées et connaître les limites de mémoire, consultez la section Android vitals - 'What are the bad behavior thresholds?.
Services perçus par l'utilisateur
Les services perceptibles sont des processus d'arrière-plan critiques que le système Android considère comme perceptibles par l'utilisateur. Cet état englobe tous les processus en cours d'exécution :
- Services de premier plan (FGS)
- Tâches accélérées
- Tâches de transfert de données déclenchées par l'utilisateur
- Services liés au système ou services liés à d'autres applications
Étant donné que les services perceptibles sont conçus pour les tâches critiques et de longue durée en arrière-plan, ils sont très sensibles aux fuites cumulatives du cycle de vie. Les limites de mémoire de la plate-forme Android traitent cet état comme n'étant pas au premier plan. Cela signifie que si votre jeu est en arrière-plan, mais continue d'exécuter un service perceptible, il est soumis aux limites de mémoire d'arrière-plan ou de service plus strictes indiquées sur la page du Centre d'aide Play. Les jeux doivent réduire de manière agressive les éléments inutiles lorsqu'ils passent d'un état de service perceptible au premier plan à un état de service perceptible en arrière-plan.
Exigences R8
Pour minimiser la taille du bytecode et réduire la surcharge de base des processus Java, Google Play Console évalue l'optimisation du code dans le cadre de ses consignes de qualité des applications. Pour en savoir plus sur la configuration de votre pipeline de compilation, consultez le guide Activer l'optimisation des applications avec R8.
Pour configurer R8 dans votre projet, suivez le guide Activer l'optimisation des applications avec R8. Pour activer les paramètres avancés de réduction et d'optimisation, consultez la section Utiliser R8 en mode complet. Pour identifier les règles qui empêchent R8 d'obscurcir les classes ou de supprimer le code mort, utilisez l'analyseur de configuration R8.
Exigences concernant les bitmaps
Les bitmaps représentent une part importante de l'utilisation de la mémoire dans les jeux modernes haute fidélité. Étant donné que les données de pixels bitmap sont stockées directement dans le tas de mémoire natif non géré sur Android 8.0 (niveau d'API 26) et versions ultérieures, le chargement d'images non optimisées peut pousser les processus au-delà des seuils de mémoire de la plate-forme. Pour connaître les bonnes pratiques concernant la mise à l'échelle et la mise en cache des images, consultez la section Optimiser l'utilisation des images.
Surveiller l'utilisation de la mémoire
Pour optimiser efficacement la mémoire de votre jeu, vous devez d'abord comprendre comment la plate-forme Android mesure son encombrement. Android 17 met à jour la métrique de mémoire pour suivre la somme du RSS anonyme (RssAnon) et de l'espace d'échange non compressé (VmSwap), à l'exclusion de la mémoire sauvegardée dans des fichiers ou privée au GPU. Ce guide explique comment tirer parti des outils au niveau du système tels que Perfetto et meminfo, implémenter des API de diagnostic telles que ProfilingManager et onTrimMemory, et extraire des allocations de mémoire précises dans Unity et Unreal Engine. Découvrez comment profiler précisément votre jeu et éviter les à-coups de performances associés à l'interrogation traditionnelle de la mémoire d'exécution.
Pour en savoir plus, consultez la section Surveiller l'utilisation de la mémoire.
Stratégies de réduction de la mémoire
Bien que les moteurs de jeu simplifient le développement multiplate-forme, leur gestion par défaut de la mémoire peut déclencher des limites de mémoire au niveau du système d'exploitation. Cette page décrit les étapes d'optimisation pratiques spécialement conçues pour Unity et Unreal Engine. Découvrez pourquoi le recours à onTrimMemory basé sur Java peut entraîner des blocages dans Unity et comment utiliser des rappels de cycle de vie natifs à la place. Vous découvrirez également des optimisations clés au niveau des éléments, telles que l'utilisation de la compression de texture ASTC 8x8 et la configuration des déchargements d'éléments, pour que votre jeu fonctionne correctement sur tous les niveaux de matériel.
Pour en savoir plus, consultez la section Réduire l'utilisation de la mémoire.