Sur la plate-forme Android, le système tente d'utiliser autant de mémoire système (RAM) que possible et effectue diverses optimisations de mémoire pour libérer de l'espace si nécessaire. Ces optimisations peuvent avoir un effet négatif sur votre jeu et le ralentir, voire le faire planter. Pour en savoir plus sur ces optimisations, consultez la page Allocation de mémoire entre les processus.
Cette page décrit les opérations à effectuer pour éviter que les problèmes de mémoire insuffisante n'affectent votre jeu.
Répondre à onTrimMemory()
Le système utilise
onTrimMemory()
pour informer votre application des événements de cycle de vie qui représentent une opportunité intéressante pour votre
afin de réduire volontairement l'utilisation de sa mémoire et d'éviter d'être tuée par le
le tueur de mémoire faible (LMK)
afin de libérer de la mémoire pour d'autres applications.
Si votre application se ferme en arrière-plan, la prochaine fois que l'utilisateur la lancera votre application, ils connaîtront une démarrage à froid Les applications qui réduisent leur l'utilisation de la mémoire en arrière-plan sont moins susceptibles d'être supprimées en arrière-plan.
Lorsque vous répondez aux événements d'édition, il est préférable de libérer de grandes allocations de mémoire
qui ne sont pas nécessaires dans l'immédiat et peuvent être reconstruits à la demande. Pour
par exemple, si votre application dispose d'un cache de bitmaps qui ont été décodés à partir de
stockées sous forme d'images compressées, il est recommandé de les éditer ou de les supprimer
en réponse à
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()) } }
Utiliser la version bêta de l'API Memory Advice
L'API Memory Advice a été développée
alternative à onTrimMemory, qui offre un rappel et une précision bien plus élevés
à prédire les LMK imminents. Pour ce faire, l'API estime la quantité
ressources de mémoire utilisées, puis en notifiant l'application lorsque certains
de service sont dépassés. L'API peut également indiquer le pourcentage estimé
l'utilisation de la mémoire
directement à votre application. Vous pouvez utiliser l'API Memory Advice
alternative à
onTrimMemory
à des fins de gestion de la mémoire.
Pour utiliser l'API Memory Advice, suivez le guide de démarrage.
Ne pas prendre de risque avec les budgets de mémoire
Définissez soigneusement ce budget pour éviter de manquer de mémoire. Voici quelques éléments à prendre en compte :
- Taille de la RAM physique : les jeux utilisent souvent entre un quart et la moitié de la RAM physique sur l'appareil.
- Taille maximale de la zRAM : plus la valeur de zRAM est élevée, plus le jeu dispose de mémoire à allouer, si nécessaire. Cette valeur peut varier en fonction de l'appareil. Recherchez
SwapTotal
dans/proc/meminfo
pour la connaître. - Utilisation de la mémoire du système d'exploitation : les appareils qui réservent davantage de RAM pour les processus système en laissent moins pour votre jeu. Un tel système arrête les processus de votre jeu avant de mettre fin à ses propres processus.
- Utilisation de la mémoire pour les applications installées : testez votre jeu sur des appareils contenant de nombreuses applications installées. Les applications de réseaux sociaux et de chat fonctionnent en permanence, ce qui réduit la quantité de mémoire disponible.
S'il vous est impossible de respecter un budget de mémoire prudent, adoptez une approche plus flexible. Si le système rencontre des problèmes de mémoire insuffisante, réduisez la quantité de mémoire utilisée par le jeu. Par exemple, allouez des textures de résolution inférieure ou stockez moins de nuanceurs en réponse à onTrimMemory()
. Cette approche dynamique de l'allocation de mémoire nécessite davantage de travail de la part du développeur, en particulier lors de la phase de conception du jeu.
Éviter le thrashing
Le thrashing se produit lorsque la mémoire disponible est faible, mais pas suffisamment faible pour provoquer l'arrêt du jeu.
Dans cette situation, kswapd
, ayant récupéré les pages dont le jeu a encore besoin, tente de les recharger à partir de la mémoire. Mais comme l'espace est insuffisant, les pages ne cessent d'être remplacées selon un phénomène d'échange continu.
Le traçage système signale cette situation sous la forme d'un thread où kswapd
s'exécute en continu.
Le thrashing peut se manifester sous la forme de délais de rendu plus importants (parfois une seconde ou plus). Réduisez l'espace mémoire utilisé par le jeu pour résoudre ce problème.
Utiliser les outils disponibles
Android dispose d'un ensemble d'outils permettant de comprendre comment le système gère la mémoire.
Meminfo
Cet outil collecte des statistiques sur la mémoire pour indiquer la quantité de mémoire PSS allouée et les catégories pour lesquelles elle a été utilisée.
Affichez les statistiques meminfo de l'une des manières suivantes :
- Exécutez la commande
adb shell dumpsys meminfo package-name
. - Utilisez l'appel
MemoryInfo
à partir de l'API Android Debug.
La valeur PrivateDirty
indique la quantité de mémoire RAM disponible dans le processus qui ne peut pas être paginée sur le disque et qui n'est partagée avec aucun autre processus. La majeure partie de cette mémoire devient disponible pour le système lorsque ce processus est arrêté.
Tracepoints pour la mémoire
Les tracepoints pour la mémoire analysent la quantité de mémoire RSS utilisée par votre jeu. Le calcul de l'utilisation de la mémoire RSS est beaucoup plus rapide que pour la mémoire PSS. Grâce à cette rapidité, les valeurs RSS offrent une meilleure visibilité sur l'évolution de la quantité de mémoire, ce qui permet des mesures plus précises des pics d'utilisation de la mémoire. Par conséquent, il est plus facile d'identifier les moment du jeu susceptibles d'entraîner des insuffisances de mémoire.
Perfetto et les traces allongées
Perfetto est une suite d'outils permettant de collecter des informations sur les performances et la mémoire d'un appareil, puis de les afficher dans une interface utilisateur Web. Comme il prend en charge les traces allongées de longueur variable, cela vous permet de suivre l'évolution des valeurs RSS au fil du temps. Vous pouvez également effectuer des requêtes SQL sur les données qu'il produit pour analyser les valeurs hors connexion. Activez les longues traces à partir de l'application de traçage système. Assurez-vous que la catégorie memory:Memory est activée pour la trace.
Heapprofd
Le daemon heapprofd
est un outil de suivi de mémoire intégré à Perfetto. Il peut vous aider à détecter les fuites de mémoire en indiquant où la mémoire a été allouée à l'aide de malloc
. heapprofd
peut être démarré à l'aide d'un script Python. Comme cet outil consomme peu de ressources, il n'affecte pas les performances comme certains autres outils tels que le débogage malloc.
bugreport
bugreport
est un outil de journalisation qui vous permet de savoir si votre jeu a planté ou non en raison d'un manque de mémoire. La sortie de l'outil est beaucoup plus détaillée que celle de Logcat. Il est utile pour le débogage de la mémoire, car il indique si votre jeu a planté en raison d'un manque de mémoire ou s'il a été arrêté par le LMK.
Pour en savoir plus, consultez Capturer et lire les rapports de bug.