Comment trouver la mémoire utilisée sur mon application Android, par programme?
J'espère qu'il y a un moyen de le faire. De plus, comment puis-je également obtenir la mémoire libre du téléphone?
java
android
memory
memory-management
Andrea Baccega
la source
la source
Réponses:
Notez que l'utilisation de la mémoire sur des systèmes d'exploitation modernes comme Linux est un domaine extrêmement compliqué et difficile à comprendre. En fait, les chances que vous interprétiez correctement les chiffres que vous obtenez sont extrêmement faibles. (À peu près chaque fois que je regarde les chiffres d'utilisation de la mémoire avec d'autres ingénieurs, il y a toujours une longue discussion sur ce qu'ils signifient réellement, ce qui ne donne qu'une vague conclusion.)
Remarque: nous avons maintenant une documentation beaucoup plus complète sur la gestion de la mémoire de votre application qui couvre une grande partie du matériel ici et est plus à jour avec l'état d'Android.
La première chose est probablement de lire la dernière partie de cet article qui explique comment la mémoire est gérée sur Android:
Modifications de l'API de service à partir d'Android 2.0
Voici maintenant
ActivityManager.getMemoryInfo()
notre API de plus haut niveau pour examiner l'utilisation globale de la mémoire. Ceci est principalement là pour aider une application à évaluer à quel point le système arrive à ne plus avoir de mémoire pour les processus d'arrière-plan, ce qui nécessite de commencer à tuer les processus nécessaires comme les services. Pour les applications Java pures, cela devrait être de peu d'utilité, car la limite de tas Java est là en partie pour éviter qu'une application ne soit en mesure de stresser le système à ce stade.À un niveau inférieur, vous pouvez utiliser l'API de débogage pour obtenir des informations brutes au niveau du noyau sur l'utilisation de la mémoire: android.os.Debug.MemoryInfo
Notez
ActivityManager.getProcessMemoryInfo
qu'à partir de la version 2.0, il existe également une API, pour obtenir ces informations sur un autre processus: ActivityManager.getProcessMemoryInfo (int [])Cela renvoie une structure MemoryInfo de bas niveau avec toutes ces données:
Mais quant à ce que la différence entre
Pss
,PrivateDirty
etSharedDirty
... eh bien maintenant le plaisir commence.Une grande partie de la mémoire dans Android (et les systèmes Linux en général) est en fait partagée entre plusieurs processus. La quantité de mémoire utilisée par un processus n'est donc pas claire. Ajoutez à cela la pagination sur le disque (et encore moins l'échange que nous n'utilisons pas sur Android) et c'est encore moins clair.
Ainsi, si vous deviez prendre toute la RAM physique réellement mappée dans chaque processus et additionner tous les processus, vous vous retrouveriez probablement avec un nombre beaucoup plus élevé que la RAM totale réelle.
Le
Pss
nombre est une métrique calculée par le noyau qui prend en compte le partage de mémoire - fondamentalement, chaque page de RAM dans un processus est mise à l'échelle par un ratio du nombre d'autres processus utilisant également cette page. De cette façon, vous pouvez (en théorie) additionner le pss sur tous les processus pour voir la RAM totale qu'ils utilisent et comparer le pss entre les processus pour avoir une idée approximative de leur poids relatif.L'autre métrique intéressante ici est
PrivateDirty
, qui est fondamentalement la quantité de RAM à l'intérieur du processus qui ne peut pas être paginée sur le disque (elle n'est pas sauvegardée par les mêmes données sur le disque), et n'est partagée avec aucun autre processus. Une autre façon de voir les choses est la RAM qui deviendra disponible pour le système lorsque ce processus disparaîtra (et sera probablement rapidement intégrée dans les caches et autres utilisations).C'est à peu près les API du SDK pour cela. Cependant, vous pouvez faire plus en tant que développeur avec votre appareil.
En utilisant
adb
, il y a beaucoup d'informations que vous pouvez obtenir sur l'utilisation de la mémoire d'un système en cours d'exécution. Une commande courante est la commandeadb shell dumpsys meminfo
qui crachera un tas d'informations sur l'utilisation de la mémoire de chaque processus Java, contenant les informations ci-dessus ainsi qu'une variété d'autres choses. Vous pouvez également mettre le nom ou le pid d'un seul processus à voir, par exemple,adb shell dumpsys meminfo system
donnez-moi le processus système:La section supérieure est la principale, où
size
est la taille totale dans l'espace d'adressage d'un tas particulier,allocated
est le kb d'allocations réelles que le tas pense avoir,free
est le kb restant libre que le tas a pour des allocations supplémentaires, etpss
etpriv dirty
sont les mêmes comme discuté avant spécifique aux pages associées à chacun des tas.Si vous souhaitez simplement examiner l'utilisation de la mémoire dans tous les processus, vous pouvez utiliser la commande
adb shell procrank
. La sortie de ceci sur le même système ressemble à:Ici, les colonnes
Vss
etRss
sont essentiellement du bruit (ce sont l'espace d'adressage simple et l'utilisation de la RAM d'un processus, où si vous additionnez l'utilisation de la RAM entre les processus, vous obtenez un nombre ridiculement élevé).Pss
est comme nous l'avons vu auparavant, etUss
estPriv Dirty
.Chose intéressante à noter ici:
Pss
etUss
sont légèrement (ou plus que légèrement) différents de ce que nous avons vumeminfo
. Pourquoi donc? Eh bien, procrank utilise un mécanisme de noyau différent pour collecter ses donnéesmeminfo
, et ils donnent des résultats légèrement différents. Pourquoi donc? Honnêtement, je n'ai aucune idée. Je crois que c'estprocrank
peut-être le plus précis ... mais vraiment, cela laisse juste le point: "prenez toutes les informations de mémoire que vous obtenez avec un grain de sel; souvent un très gros grain."Enfin, il y a la commande
adb shell cat /proc/meminfo
qui donne un résumé de l'utilisation globale de la mémoire du système. Il y a beaucoup de données ici, seuls les premiers chiffres méritent d'être discutés (et les autres sont compris par peu de gens, et mes questions à ces quelques personnes à leur sujet entraînent souvent des explications contradictoires):MemTotal
est la quantité totale de mémoire disponible pour le noyau et l'espace utilisateur (souvent inférieure à la RAM physique réelle du périphérique, car une partie de cette RAM est nécessaire pour la radio, les tampons DMA, etc.).MemFree
est la quantité de RAM qui n'est pas utilisée du tout. Le nombre que vous voyez ici est très élevé; généralement sur un système Android, cela ne représente que quelques Mo, car nous essayons d'utiliser la mémoire disponible pour maintenir les processus en coursCached
est la RAM utilisée pour les caches du système de fichiers et d'autres choses de ce type. Les systèmes typiques devront avoir environ 20 Mo pour éviter d’entrer dans de mauvais états de pagination; Android tueur de mémoire est réglé pour un système particulier afin de s'assurer que les processus d'arrière-plan sont supprimés avant que la RAM mise en cache ne soit trop consommée par eux pour entraîner une telle pagination.la source
Oui, vous pouvez obtenir des informations sur la mémoire par programme et décider d'effectuer un travail gourmand en mémoire.
Obtenez VM Heap Size en appelant:
Obtenez la mémoire VM allouée en appelant:
Obtenez VM Heap Size Limit en appelant:
Obtenez la mémoire allouée native en appelant:
J'ai créé une application pour comprendre le comportement de OutOfMemoryError et surveiller l'utilisation de la mémoire.
https://play.google.com/store/apps/details?id=net.coocood.oomresearch
Vous pouvez obtenir le code source sur https://github.com/coocood/oom-research
la source
C'est un travail en cours, mais c'est ce que je ne comprends pas:
Pourquoi le PID n'est-il pas mappé au résultat dans activityManager.getProcessMemoryInfo ()? De toute évidence, vous voulez rendre les données résultantes significatives, alors pourquoi Google a-t-il rendu si difficile la corrélation des résultats? Le système actuel ne fonctionne même pas bien si je veux traiter l'intégralité de l'utilisation de la mémoire car le résultat renvoyé est un tableau d'objets android.os.Debug.MemoryInfo, mais aucun de ces objets ne vous indique réellement à quels pids ils sont associés. Si vous passez simplement un tableau de tous les pids, vous n'aurez aucun moyen de comprendre les résultats. Si je comprends bien son utilisation, cela rend inutile de passer plus d'un pid à la fois, puis si c'est le cas, pourquoi faire en sorte que activityManager.getProcessMemoryInfo () ne prenne qu'un tableau int?
la source
Hackbod's est l'une des meilleures réponses sur Stack Overflow. Il éclaire un sujet très obscur. Cela m'a beaucoup aidé.
Une autre ressource vraiment utile est cette vidéo incontournable: Google I / O 2011: Gestion de la mémoire pour les applications Android
MISE À JOUR:
Process Stats, un service pour découvrir comment votre application gère la mémoire expliqué dans l'article de blog Process Stats: Comprendre comment votre application utilise la RAM par Dianne Hackborn:
la source
Android Studio 0.8.10+ a introduit un outil incroyablement utile appelé Memory Monitor .
À quoi ça sert:
Figure 1. Forcer un événement GC (Garbage Collection) sur Android Memory Monitor
Vous pouvez avoir beaucoup de bonnes informations sur la consommation de RAM en temps réel de votre application en l'utilisant.
la source
1) Je suppose que non, du moins pas de Java.
2)
la source
Nous avons découvert que toutes les méthodes standard pour obtenir la mémoire totale du processus actuel ont quelques problèmes.
Runtime.getRuntime().totalMemory()
: renvoie uniquement la mémoire JVMActivityManager.getMemoryInfo()
,Process.getFreeMemory()
et tout autre élément basé sur/proc/meminfo
- renvoie des informations sur la mémoire de tous les processus combinés (par exemple android_util_Process.cpp )Debug.getNativeHeapAllocatedSize()
- utilisationsmallinfo()
qui retournent des informations sur les allocations de mémoire effectuées parmalloc()
et les fonctions associées uniquement (voir android_os_Debug.cpp )Debug.getMemoryInfo()
- fait le boulot mais c'est trop lent. Cela prend environ 200 ms sur le Nexus 6 pour un seul appel. La surcharge de performances rend cette fonction inutile pour nous car nous l'appelons régulièrement et chaque appel est assez perceptible (voir android_os_Debug.cpp )ActivityManager.getProcessMemoryInfo(int[])
- appels enDebug.getMemoryInfo()
interne (voir ActivityManagerService.java )Enfin, nous avons fini par utiliser le code suivant:
Il renvoie la métrique VmRSS . Vous pouvez trouver plus de détails à ce sujet ici: un , deux et trois .
PS J'ai remarqué que le thème manque toujours d'un extrait de code réel et simple sur la façon d' estimer l'utilisation de la mémoire privée du processus si les performances ne sont pas une exigence critique:
la source
Dans Android Studio 3.0, ils ont introduit Android-profiler pour vous aider à comprendre comment votre application utilise les ressources CPU, mémoire, réseau et batterie.
https://developer.android.com/studio/profile/android-profiler
la source
Il y a beaucoup de réponses ci-dessus qui vous aideront certainement, mais (après 2 jours de moyens et de recherches sur les outils de mémoire adb), je pense que je peux aussi aider avec mon opinion .
Comme le dit Hackbod: Ainsi, si vous deviez prendre toute la RAM physique réellement mappée dans chaque processus et additionner tous les processus, vous vous retrouveriez probablement avec un nombre beaucoup plus élevé que la RAM totale réelle. il n'y a donc aucun moyen d'obtenir la quantité exacte de mémoire par processus.
Mais vous pouvez vous en approcher par une logique .. et je vais vous dire comment ..
Donc, tout d'abord, vous devez être un utilisateur root pour le faire fonctionner. Accédez à la console avec le privilège root en exécutant
su
in process et obtenez sonoutput and input stream
. Ensuite, passezid\n
(entrez) dans ouputstream et écrivez-le pour traiter la sortie, si vous obtiendrez un flux d'entrée contenantuid=0
, vous êtes l'utilisateur root.Voici maintenant la logique que vous utiliserez dans le processus ci-dessus
Lorsque vous obtenez ouputstream de processus passez votre commande (procrank, dumpsys meminfo etc ...) avec
\n
au lieu de id et obtenez soninputstream
et lisez, stockez le flux en octets [], char [] etc. utilisez des données brutes .. et vous sont fait!!!!!autorisation :
Vérifiez si vous êtes root:
Exécutez votre commande avec
su
logcat:
Ceci est juste un essai, veuillez me suggérer si j'ai raté quelque chose
la source