web-dev-qa-db-fra.com

Comment obtenir l'utilisation actuelle de la mémoire sous Android?

J'ai utilisé/proc/meminfo et la réponse analysée de la commande. Cependant, le résultat montre que: 

MemTotal: 94348 kB MemFree: 5784 kB

veux dire. cela montre qu'il n'y a que 5 Mo de mémoire disponible. Est-ce possible avec Android mobile? Il n'y a que 5 ou 6 applications installées sur mon mobile et aucune autre tâche n'est en cours d'exécution. mais toujours cette commande montre qu'il y a très peu de mémoire libre.

Quelqu'un peut-il clarifier cela? ou existe-t-il un autre moyen d'obtenir l'utilisation de la mémoire sous Android?

93
Badal

ATTENTION: Cette réponse mesure l'utilisation de la mémoire/disponible du PÉRIPHÉRIQUE. Ce n'est pas ce qui est disponible pour votre application. Pour mesurer ce que votre APP fait et est autorisé à faire, Utilisez la réponse du développeur Android .


Documents Android - ActivityManager.MemoryInfo

  1. commande/proc/meminfo. Vous pouvez trouver le code de référence ici: Obtenir l'utilisation de la mémoire sous Android

  2. utilisez le code ci-dessous et obtenez la RAM actuelle:

    MemoryInfo mi = new MemoryInfo();
    ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
    activityManager.getMemoryInfo(mi);
    double availableMegs = mi.availMem / 0x100000L;
    
    //Percentage can be calculated for API 16+
    double percentAvail = mi.availMem / (double)mi.totalMem * 100.0;
    

Explication du nombre 0x100000L 

1024 bytes      == 1 Kibibyte 
1024 Kibibyte   == 1 Mebibyte

1024 * 1024     == 1048576
1048576         == 0x100000

Il est assez évident que le nombre est utilisé pour convertir des octets en mebibyte

P.S: nous n'avons besoin de calculer la mémoire totale qu'une seule fois. alors appelez le point 1 une seule fois dans votre code, puis après, vous pourrez appeler le code du point 2 de manière répétée.

155
Badal

Cela dépend de votre définition de la requête mémoire que vous souhaitez obtenir.


En règle générale, vous souhaitez connaître l'état de la mémoire de tas, car s'il utilise trop de mémoire, vous obtenez le MOO et vous bloquez l'application.

Pour cela, vous pouvez vérifier les valeurs suivantes:

final Runtime runtime = Runtime.getRuntime();
final long usedMemInMB=(runtime.totalMemory() - runtime.freeMemory()) / 1048576L;
final long maxHeapSizeInMB=runtime.maxMemory() / 1048576L;
final long availHeapSizeInMB = maxHeapSizeInMB - usedMemInMB;

Plus la variable "usedMemInMB" se rapproche de "maxHeapSizeInMB", plus availHeapSizeInMB se rapproche de zéro, plus vous vous rapprochez de MOO. (En raison de la fragmentation de la mémoire, vous pouvez obtenir un MOO avant que la valeur ne soit nulle.)

C’est aussi ce que montre l’outil DDMS d’utilisation de la mémoire.


Il existe également une utilisation réelle RAM, qui correspond à la quantité utilisée par tout le système - voir réponse acceptée pour la calculer.


Mise à jour: dans la mesure où Android O fait également en sorte que votre application utilise également la RAM native (du moins pour le stockage Bitmaps, qui est généralement la principale raison d'une utilisation importante de la mémoire), et pas seulement le tas, les choses ont changé et vous obtenez moins MOO (car le tas ne contient plus de bitmaps, vérifiez ici ), mais gardez toujours un œil sur l'utilisation de la mémoire si vous pensez que vous avez des fuites de mémoire. Sur Android O, si vous avez des fuites de mémoire qui auraient pu entraîner la présence de MOO sur des versions plus anciennes, il semble que le système se plantera sans que vous ne puissiez l’attraper. Voici comment vérifier l'utilisation de la mémoire:

 val nativeHeapSize = Debug.getNativeHeapSize()
 val nativeHeapFreeSize = Debug.getNativeHeapFreeSize()
 val usedMemInBytes = nativeHeapSize - nativeHeapFreeSize
 val usedMemInPercentage = usedMemInBytes * 100 / nativeHeapSize

Mais je pense qu'il serait préférable d'utiliser le profileur de l'EDI, qui affiche les données en temps réel, à l'aide d'un graphique. 

La bonne nouvelle sur Android O est donc qu'il est beaucoup plus difficile de provoquer des accidents du fait que OOM stocke trop de bitmaps volumineux, mais la mauvaise nouvelle est qu'il ne me semble pas possible d'attraper un tel cas pendant l'exécution. 

60

Voici un moyen de calculer l'utilisation de la mémoire de l'application en cours d'exécution :

public static long getUsedMemorySize() {

    long freeSize = 0L;
    long totalSize = 0L;
    long usedSize = -1L;
    try {
        Runtime info = Runtime.getRuntime();
        freeSize = info.freeMemory();
        totalSize = info.totalMemory();
        usedSize = totalSize - freeSize;
    } catch (Exception e) {
        e.printStackTrace();
    }
    return usedSize;

}
28
Sharmilee

Une autre façon (25 Mo actuellement disponibles sur mon G1):

MemoryInfo mi = new MemoryInfo();
ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
activityManager.getMemoryInfo(mi);
long availableMegs = mi.availMem / 1048576L;
17
yanchenko

La philosophie de gestion de la mémoire de Linux est la suivante: "La mémoire libre est une mémoire perdue".

Je suppose que les deux lignes suivantes montreront combien de mémoire est dans "Tampons" et combien est "Caché". Bien qu'il existe une différence entre les deux (veuillez ne pas demander en quoi cette différence est :): ils ajoutent à peu près la quantité de mémoire utilisée pour mettre en cache les données de fichier et les métadonnées.

La commande free(1) constitue un guide beaucoup plus utile pour libérer de la mémoire sur un système Linux. sur mon bureau, il rapporte des informations comme ceci:

 $ free -m 
 nombre total de tampons partagés libres utilisés et mis en cache 
 Mem: 5980 1055 4924 0 91 374 
-/+ tampons/cache: 589 5391 
 Permutation: 6347 0 6347 

La ligne +/- buffers/cache: est la ligne magique. Elle indique que j'ai vraiment environ 589 Mo de mémoire de processus activement requise, et environ 5391 Mo de mémoire «libre», en ce sens que les 91 + 374 mégaoctets de mémoire tampon/mémoire cache peut être jeté si la mémoire peut être utilisée de manière plus rentable ailleurs.

(Ma machine est en marche depuis environ trois heures et ne fait presque rien, mais stackoverflow, c'est pourquoi j'ai tellement de mémoire disponible.)

Si Android ne contient pas free(1), vous pouvez effectuer le calcul vous-même avec le fichier /proc/meminfo; J'aime juste le format de sortie free(1). :)

12
sarnold

Je me réfère à quelques écrits.

référence:

Cette méthode getMemorySize () renvoie MemorySize avec une taille de mémoire totale et libre.
Je ne crois pas ce code parfaitement.
Ce code teste sur LG G3 cat.6 (v5.0.1)

    private MemorySize getMemorySize() {
        final Pattern PATTERN = Pattern.compile("([a-zA-Z]+):\\s*(\\d+)");

        MemorySize result = new MemorySize();
        String line;
        try {
            RandomAccessFile reader = new RandomAccessFile("/proc/meminfo", "r");
            while ((line = reader.readLine()) != null) {
                Matcher m = PATTERN.matcher(line);
                if (m.find()) {
                    String name = m.group(1);
                    String size = m.group(2);

                    if (name.equalsIgnoreCase("MemTotal")) {
                        result.total = Long.parseLong(size);
                    } else if (name.equalsIgnoreCase("MemFree") || name.equalsIgnoreCase("Buffers") ||
                            name.equalsIgnoreCase("Cached") || name.equalsIgnoreCase("SwapFree")) {
                        result.free += Long.parseLong(size);
                    }
                }
            }
            reader.close();

            result.total *= 1024;
            result.free *= 1024;
        } catch (IOException e) {
            e.printStackTrace();
        }

        return result;
    }

    private static class MemorySize {
        public long total = 0;
        public long free = 0;
    }

Je sais que Pattern.compile () coûte cher, vous pouvez donc déplacer son code vers un membre de la classe.

6
Hogun

J'ai regardé l'arbre source Android.

Dans com.Android.server.am .ActivityManagerService.Java (service interne exposé par Android.app .ActivityManager).

public void getMemoryInfo(ActivityManager.MemoryInfo outInfo) {
    final long homeAppMem = mProcessList.getMemLevel(ProcessList.HOME_APP_ADJ);
    final long hiddenAppMem = mProcessList.getMemLevel(ProcessList.HIDDEN_APP_MIN_ADJ);
    outInfo.availMem = Process.getFreeMemory();
    outInfo.totalMem = Process.getTotalMemory();
    outInfo.threshold = homeAppMem;
    outInfo.lowMemory = outInfo.availMem < (homeAppMem + ((hiddenAppMem-homeAppMem)/2));
    outInfo.hiddenAppThreshold = hiddenAppMem;
    outInfo.secondaryServerThreshold = mProcessList.getMemLevel(
            ProcessList.SERVICE_ADJ);
    outInfo.visibleAppThreshold = mProcessList.getMemLevel(
            ProcessList.VISIBLE_APP_ADJ);
    outInfo.foregroundAppThreshold = mProcessList.getMemLevel(
            ProcessList.FOREGROUND_APP_ADJ);
}

Dans Android.os .Process.Java

/** @hide */
public static final native long getFreeMemory();

/** @hide */
public static final native long getTotalMemory();

Il appelle la méthode JNI depuis Android_util_Process.cpp

Conclusion

MemoryInfo.availMem = MemFree + Mis en cache dans/proc/meminfo.

Remarques

La mémoire totale est ajoutée au niveau 16 de l'API.

3
ragazenta

vous pouvez également utiliser l'outil DDMS, qui fait partie du SDK Android, lui-même . Il aide également à obtenir les allocations de mémoire du code Java et du code natif c/c ++.

1
vsmph
final long usedMemInMB=(runtime.totalMemory() - runtime.freeMemory()) / 1048576L;
final long maxHeapSizeInMB=runtime.maxMemory() / 1048576L;
final long availHeapSizeInMB = maxHeapSizeInMB - usedMemInMB;

C'est un code étrange. Il retourne MaxMemory - (totalMemory - freeMemory). Si freeMemory est égal à 0, le code renverra MaxMemory - totalMemory, de sorte qu'il puisse être supérieur ou égal à 0. Pourquoi freeMemory n'est pas utilisé?

0
Andrey
public static boolean isAppInLowMemory(Context context) {
    ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
    ActivityManager.MemoryInfo memoryInfo = new ActivityManager.MemoryInfo();
    activityManager.getMemoryInfo(memoryInfo);

    return memoryInfo.lowMemory;
}
0
iMobaio