Comment puis-je trouver la mémoire utilisée sur mon application Android, de manière programmatique ?
J'espère qu'il y a un moyen de le faire. De plus, comment puis-je obtenir la mémoire libre du téléphone aussi ?
Comment puis-je trouver la mémoire utilisée sur mon application Android, de manière programmatique ?
J'espère qu'il y a un moyen de le faire. De plus, comment puis-je obtenir la mémoire libre du téléphone aussi ?
Notez que l'utilisation de la mémoire sur les systèmes d'exploitation modernes comme Linux est une extrêmement domaine compliqué et difficile à comprendre. En fait, les chances que vous interprétiez correctement les chiffres que vous obtenez sont extrêmement faibles. (Pratiquement chaque fois que j'examine 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 qui ne débouche que sur une vague conclusion).
Note : nous disposons désormais d'une documentation beaucoup plus complète sur 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 à faire est probablement de lire la dernière partie de cet article qui traite de la manière dont la mémoire est gérée sur Android :
Changements de l'API de service à partir d'Android 2.0
Maintenant ActivityManager.getMemoryInfo()
est notre API de plus haut niveau pour examiner l'utilisation globale de la mémoire. Elle est principalement destinée à aider une application à évaluer dans quelle mesure le système est sur le point de ne plus avoir de mémoire pour les processus d'arrière-plan, et donc de devoir commencer à tuer les processus nécessaires comme les services. Pour les applications purement Java, cela ne devrait pas être très utile, puisque la limite du tas Java est là en partie pour éviter qu'une application puisse stresser le système à ce point.
En allant plus bas, 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 qu'à partir de la version 2.0, il existe également une API, ActivityManager.getProcessMemoryInfo
pour obtenir cette information sur un autre processus : ActivityManager.getProcessMemoryInfo(int[])
Cela renvoie une structure MemoryInfo de bas niveau avec toutes ces données :
/** The proportional set size for dalvik. */
public int dalvikPss;
/** The private dirty pages used by dalvik. */
public int dalvikPrivateDirty;
/** The shared dirty pages used by dalvik. */
public int dalvikSharedDirty;
/** The proportional set size for the native heap. */
public int nativePss;
/** The private dirty pages used by the native heap. */
public int nativePrivateDirty;
/** The shared dirty pages used by the native heap. */
public int nativeSharedDirty;
/** The proportional set size for everything else. */
public int otherPss;
/** The private dirty pages used by everything else. */
public int otherPrivateDirty;
/** The shared dirty pages used by everything else. */
public int otherSharedDirty;
Mais quant à la différence entre Pss
, PrivateDirty
y SharedDirty
... et maintenant le plaisir commence.
Une grande partie de la mémoire d'Android (et des systèmes Linux en général) est en fait partagée entre plusieurs processus. Ainsi, la quantité de mémoire utilisée par un processus n'est pas vraiment claire. Si l'on ajoute à cela la pagination sur le disque (sans parler du swap que nous n'utilisons pas sous Android), la situation est encore moins claire.
Ainsi, si vous deviez prendre toute la mémoire vive physique réellement affectée à chaque processus et additionner tous les processus, vous obtiendriez probablement un nombre bien supérieur à la mémoire vive totale réelle.
El Pss
est une métrique calculée par le noyau qui prend en compte le partage de la mémoire -- en gros, 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 les pss de tous les processus pour connaître la RAM totale qu'ils utilisent, et comparer les pss entre les processus pour avoir une idée approximative de leur poids relatif.
L'autre mesure intéressante ici est PrivateDirty
Il s'agit essentiellement de 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 qui n'est pas partagée avec d'autres 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 probablement rapidement subsumée dans les caches et autres utilisations).
C'est à peu près l'API du SDK pour cela. Cependant, en tant que développeur, vous pouvez faire plus avec votre appareil.
Utilisation de adb
il y a beaucoup d'informations que vous pouvez obtenir sur l'utilisation de la mémoire d'un système en fonctionnement. Un exemple courant est la commande adb shell dumpsys meminfo
qui fournira 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 aussi ajouter le nom ou le pid d'un seul processus pour voir, par exemple adb shell dumpsys meminfo system
donnez-moi le processus du système :
\*\* MEMINFO in pid 890 \[system\] \*\*
native dalvik other total
size: 10940 7047 N/A 17987
allocated: 8943 5516 N/A 14459
free: 336 1531 N/A 1867
(Pss): 4585 9282 11916 25783
(shared dirty): 2184 3596 916 6696
(priv dirty): 4504 5956 7456 17916
Objects
Views: 149 ViewRoots: 4
AppContexts: 13 Activities: 0
Assets: 4 AssetManagers: 4
Local Binders: 141 Proxy Binders: 158
Death Recipients: 49
OpenSSL Sockets: 0
SQL
heap: 205 dbFiles: 0
numPagers: 0 inactivePageKB: 0
activePageKB: 0
La section supérieure est la principale, où size
est la taille totale de l'espace d'adressage d'un tas particulier, allocated
est le kb d'allocations réelles que le tas pense avoir, free
est le nombre de kb restants libres dans le tas pour des allocations supplémentaires, et pss
y priv dirty
sont les mêmes que ceux discutés précédemment, spécifiques aux pages associées à chacun des tas.
Si vous voulez simplement regarder l'utilisation de la mémoire pour tous les processus, vous pouvez utiliser la commande adb shell procrank
. Le résultat de cette opération sur le même système ressemble à ceci :
PID Vss Rss Pss Uss cmdline
890 84456K 48668K 25850K 21284K system\_server
1231 50748K 39088K 17587K 13792K com.android.launcher2
947 34488K 28528K 10834K 9308K com.android.wallpaper
987 26964K 26956K 8751K 7308K com.google.process.gapps
954 24300K 24296K 6249K 4824K com.android.phone
948 23020K 23016K 5864K 4748K com.android.inputmethod.latin
888 25728K 25724K 5774K 3668K zygote
977 24100K 24096K 5667K 4340K android.process.acore
...
59 336K 332K 99K 92K /system/bin/installd
60 396K 392K 93K 84K /system/bin/keystore
51 280K 276K 74K 68K /system/bin/servicemanager
54 256K 252K 69K 64K /system/bin/debuggerd
Ici, le Vss
y Rss
sont essentiellement du bruit (il s'agit de l'espace d'adressage et de 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 grand).
Pss
est comme nous l'avons vu auparavant, et Uss
es Priv Dirty
.
Une chose intéressante à noter ici : Pss
y Uss
sont légèrement (ou plus que légèrement) différents de ceux que nous avons vus en meminfo
. Pourquoi ? Eh bien procrank utilise un mécanisme de noyau différent pour collecter ses données par rapport à meminfo
le fait, et ils donnent des résultats légèrement différents. Pourquoi cela ? Honnêtement, je n'en ai pas la moindre idée. Je crois procrank
est peut-être le plus précis... mais en fait, cela ne fait que laisser le point : "prenez toute information sur la 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 valent la peine d'être discutés (et les autres sont compris par peu de personnes, et mes questions à ces quelques personnes à leur sujet aboutissent souvent à des explications contradictoires) :
MemTotal: 395144 kB
MemFree: 184936 kB
Buffers: 880 kB
Cached: 84104 kB
SwapCached: 0 kB
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, puisqu'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é ; typiquement, sur un système Android, il ne s'agit que de quelques Mo, puisque nous essayons d'utiliser la mémoire disponible pour faire tourner les processus.
Cached
est la RAM utilisée pour les caches des systèmes de fichiers et autres. Les systèmes typiques ont besoin d'environ 20 Mo pour éviter les états de pagination. Le tueur de mémoire d'Android est réglé pour un système particulier afin de s'assurer que les processus d'arrière-plan sont tués avant que la mémoire vive en cache ne soit trop consommée par eux pour entraîner une telle pagination.
Jetez un coup d'œil à pixelbeat.org/scripts/ps_mem.py qui utilise les techniques mentionnées ci-dessus pour montrer la RAM utilisée pour les programmes
Très bien écrit ! J'ai écrit un article sur la gestion de la mémoire et l'utilisation de différents outils pour inspecter l'utilisation du tas ici. macgyverdev.blogspot.com/2011/11/ si quelqu'un le trouve utile.
Oui, vous pouvez obtenir des informations sur la mémoire de manière programmatique et décider d'effectuer ou non un travail nécessitant beaucoup de mémoire.
Obtenir la taille du tas de la VM en appelant :
Runtime.getRuntime().totalMemory();
Obtenir la mémoire VM allouée en appelant :
Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
Obtenir la limite de la taille du tas de la VM en appelant :
Runtime.getRuntime().maxMemory()
Obtenir la mémoire native allouée en appelant :
Debug.getNativeHeapAllocatedSize();
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 à l'adresse suivante https://github.com/coocood/oom-research
Ce runtime renvoie-t-il l'utilisation de la mémoire par le processus en cours ou par le tas global du système ?
@mahemadhi de la JavaDoc de la méthode totalMemory() "Renvoie la quantité totale de mémoire disponible pour le programme en cours d'exécution".
C'est un travail en cours, mais voici ce que je ne comprends pas :
ActivityManager activityManager = (ActivityManager) context.getSystemService(ACTIVITY_SERVICE);
MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
activityManager.getMemoryInfo(memoryInfo);
Log.i(TAG, " memoryInfo.availMem " + memoryInfo.availMem + "\n" );
Log.i(TAG, " memoryInfo.lowMemory " + memoryInfo.lowMemory + "\n" );
Log.i(TAG, " memoryInfo.threshold " + memoryInfo.threshold + "\n" );
List<RunningAppProcessInfo> runningAppProcesses = activityManager.getRunningAppProcesses();
Map<Integer, String> pidMap = new TreeMap<Integer, String>();
for (RunningAppProcessInfo runningAppProcessInfo : runningAppProcesses)
{
pidMap.put(runningAppProcessInfo.pid, runningAppProcessInfo.processName);
}
Collection<Integer> keys = pidMap.keySet();
for(int key : keys)
{
int pids[] = new int[1];
pids[0] = key;
android.os.Debug.MemoryInfo[] memoryInfoArray = activityManager.getProcessMemoryInfo(pids);
for(android.os.Debug.MemoryInfo pidMemoryInfo: memoryInfoArray)
{
Log.i(TAG, String.format("** MEMINFO in pid %d [%s] **\n",pids[0],pidMap.get(pids[0])));
Log.i(TAG, " pidMemoryInfo.getTotalPrivateDirty(): " + pidMemoryInfo.getTotalPrivateDirty() + "\n");
Log.i(TAG, " pidMemoryInfo.getTotalPss(): " + pidMemoryInfo.getTotalPss() + "\n");
Log.i(TAG, " pidMemoryInfo.getTotalSharedDirty(): " + pidMemoryInfo.getTotalSharedDirty() + "\n");
}
}
Pourquoi le PID n'est-il pas associé au résultat dans activityManager.getProcessMemoryInfo() ? Il est clair que vous voulez que les données résultantes soient 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 la totalité de l'utilisation de la mémoire puisque le résultat retourné 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 dans un tableau de tous les pids, vous n'aurez aucun moyen de comprendre les résultats. Si je comprends son utilisation, il est inutile de passer plus d'un pid à la fois, et si c'est le cas, pourquoi faire en sorte que activityManager.getProcessMemoryInfo() prenne seulement un tableau d'int ?
Cela semble être une façon très peu intuitive de faire les choses. Oui, c'est probablement le cas, mais en quoi est-ce une façon de faire de la POO ?
L'API a été conçue pour l'efficacité, et non pour la facilité d'utilisation ou la simplicité. Ce n'est tout simplement pas quelque chose que 99 % des applications devraient toucher, l'efficacité est donc l'objectif de conception le plus important.
La réponse de Hackbod est l'une des meilleures réponses sur Stack Overflow. Elle fait la lumière sur un sujet très obscur. Elle m'a beaucoup aidé.
Une autre ressource très utile est cette vidéo à voir absolument : Google I/O 2011 : Gestion de la mémoire pour les applications Android
UPDATE :
Process Stats, un service permettant de découvrir comment votre application gère la mémoire, expliqué dans l'article du blogue Statistiques des processus : Comprendre comment votre application utilise la RAM par Dianne Hackborn :
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.
2 votes
Ou si quelqu'un veut en savoir plus sur tout cela, veuillez vous référer à http://elinux.org/Android_Memory_Usage
1 votes
Gérer la mémoire de votre application developer.Android.com/topic/performance/memory