java - ver - ¿Cómo descubro el uso de memoria de mi aplicación en Android?




ver memoria ram android 8 (6)

1) Supongo que no, al menos no de Java.
2)

ActivityManager activityManager = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
MemoryInfo mi = new MemoryInfo();
activityManager.getMemoryInfo(mi);
Log.i("memory free", "" + mi.availMem);

https://code.i-harness.com

¿Cómo puedo encontrar la memoria utilizada en mi aplicación de Android, mediante programación?

Espero que haya una manera de hacerlo. Además, ¿cómo consigo la memoria libre del teléfono también?


Android Studio 0.8.10+ ha introducido una herramienta increíblemente útil llamada Memory Monitor .

Lo que es bueno para:

  • Mostrar la memoria disponible y utilizada en un gráfico y los eventos de recolección de basura a lo largo del tiempo.
  • Probar rápidamente si la lentitud de la aplicación podría estar relacionada con eventos de recolección excesiva de basura.
  • Probar rápidamente si los bloqueos de aplicaciones pueden estar relacionados con quedarse sin memoria.

Figura 1. Forzar un evento GC (recolección de basura) en el monitor de memoria de Android

Puede tener mucha información buena sobre el consumo de RAM en tiempo real de su aplicación al usarla.


Este es un trabajo en progreso, pero esto es lo que no entiendo:

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");
    }
}

¿Por qué no se asigna el PID al resultado en activityManager.getProcessMemoryInfo ()? Es evidente que desea que los datos resultantes sean significativos, así que ¿por qué Google ha hecho que sea tan difícil correlacionar los resultados? El sistema actual ni siquiera funciona bien si quiero procesar todo el uso de la memoria, ya que el resultado devuelto es una matriz de objetos android.os.Debug.MemoryInfo, pero ninguno de esos objetos realmente le dice a qué pids están asociados. Si simplemente pasa una serie de todos los pids, no tendrá forma de entender los resultados. Como entiendo su uso, no tiene sentido pasar más de un pid a la vez, y si ese es el caso, ¿por qué hacerlo para que activityManager.getProcessMemoryInfo () solo tome una matriz int?



Sí, puede obtener información de la memoria mediante programación y decidir si realizar un trabajo de memoria intensiva.

Obtenga VM Hize Size llamando a:

Runtime.getRuntime().totalMemory();

Obtenga memoria virtual asignada llamando a:

Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();

Obtenga el límite de tamaño de pila de VM llamando a:

Runtime.getRuntime().maxMemory()

Obtenga memoria asignada nativa llamando a:

Debug.getNativeHeapAllocatedSize();

Hice una aplicación para descubrir el comportamiento de OutOfMemoryError y monitorear el uso de la memoria.

https://play.google.com/store/apps/details?id=net.coocood.oomresearch

Puede obtener el código fuente en https://github.com/coocood/oom-research


Tenga en cuenta que el uso de memoria en sistemas operativos modernos como Linux es un área extremadamente complicada y difícil de entender. De hecho, las posibilidades de que realmente interpretes correctamente los números que obtienes son extremadamente bajas. (Casi cada vez que miro los números de uso de la memoria con otros ingenieros, siempre hay una larga discusión sobre lo que realmente significa que solo resulta en una conclusión vaga).

Nota: ahora tenemos una documentación mucho más extensa sobre la gestión de la memoria de su aplicación que cubre gran parte del material aquí y está más actualizada con el estado de Android.

Lo primero es leer la última parte de este artículo, que contiene un análisis de cómo se gestiona la memoria en Android:

Cambios en la API del servicio a partir de Android 2.0

Ahora ActivityManager.getMemoryInfo() es nuestra API de más alto nivel para observar el uso general de la memoria. Esto es principalmente para ayudar a una aplicación a medir qué tan cerca está el sistema de no tener más memoria para los procesos en segundo plano, por lo que debe comenzar a eliminar los procesos necesarios como los servicios. Para aplicaciones Java puras, esto debería ser de poca utilidad, ya que el límite de almacenamiento dinámico de Java está en parte para evitar que una aplicación pueda estresar el sistema hasta este punto.

Al ir a un nivel inferior, puede usar la API de depuración para obtener información en bruto del nivel de kernel sobre el uso de la memoria: android.os.Debug.MemoryInfo

Tenga en cuenta que a partir de 2.0 también hay una API, ActivityManager.getProcessMemoryInfo , para obtener esta información sobre otro proceso: ActivityManager.getProcessMemoryInfo(int[])

Esto devuelve una estructura MemoryInfo de bajo nivel con todos estos datos:

    /** 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;

Pero en cuanto a cuál es la diferencia entre Pss , PrivateDirty y SharedDirty ... bueno, ahora comienza la diversión.

Una gran cantidad de memoria en Android (y en los sistemas Linux en general) en realidad se comparte a través de múltiples procesos. Entonces, la cantidad de memoria que utiliza un proceso realmente no está clara. Agregue encima de esa paginación al disco (y mucho menos intercambie lo que no usamos en Android) y es aún menos claro.

Por lo tanto, si tuviera que tomar toda la RAM física asignada a cada proceso, y sumara todos los procesos, probablemente terminaría con un número mucho mayor que la RAM total real.

El número de Pss es una métrica que el núcleo calcula que toma en cuenta el uso compartido de memoria: básicamente, cada página de RAM en un proceso se escala en una proporción del número de otros procesos que también usan esa página. De esta manera puede (en teoría) sumar los pss en todos los procesos para ver la RAM total que están utilizando y comparar los pss entre procesos para tener una idea aproximada de su peso relativo.

La otra métrica interesante aquí es PrivateDirty , que es básicamente la cantidad de RAM dentro del proceso que no se puede paginar en el disco (no está respaldada por los mismos datos en el disco) y no se comparte con ningún otro proceso. Otra forma de ver esto es la memoria RAM que estará disponible para el sistema cuando el proceso desaparezca (y probablemente se subsume rápidamente en cachés y otros usos del mismo).

Eso es más o menos las API del SDK para esto. Sin embargo, hay más que puedes hacer como desarrollador con tu dispositivo.

Al usar adb , hay mucha información que puede obtener sobre el uso de la memoria de un sistema en ejecución. Uno común es el comando adb shell dumpsys meminfo que adb shell dumpsys meminfo un montón de información sobre el uso de la memoria de cada proceso de Java, que contiene la información anterior, así como una variedad de otras cosas. También puede agregar el nombre o el pid de un solo proceso para ver, por ejemplo, el adb shell dumpsys meminfo system dame el proceso del sistema:

** 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 sección superior es la principal, donde size es el tamaño total en el espacio de direcciones de un montón particular, allocated es el kb de asignaciones reales que el montón cree que tiene, free es el kb restante que el montón tiene para asignaciones adicionales, y pss y priv dirty son los mismos que se analizaron antes de las páginas asociadas con cada uno de los montones.

Si solo desea ver el uso de la memoria en todos los procesos, puede usar el comando adb shell procrank . La salida de esto en el mismo sistema se ve así:

  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

Aquí, las columnas Vss y Rss son básicamente ruido (son el espacio de direcciones directo y el uso de RAM de un proceso, donde si sumas el uso de RAM en todos los procesos obtienes un número ridículamente grande).

Pss es como hemos visto antes, y Uss es Priv Dirty .

Una cosa interesante a tener en cuenta aquí: Pss y Uss son ligeramente (o más que ligeramente) diferentes a lo que vimos en meminfo . ¿Porqué es eso? Well procrank utiliza un mecanismo de kernel diferente para recopilar sus datos que meminfo , y dan resultados ligeramente diferentes. ¿Porqué es eso? Sinceramente no tengo ni idea. Creo que procrank puede ser el más exacto ... pero en realidad, simplemente deje el punto: "tome cualquier información de memoria que obtenga con un grano de sal; a menudo un grano muy grande".

Finalmente, está el comando adb shell cat /proc/meminfo que proporciona un resumen del uso general de memoria del sistema. Aquí hay una gran cantidad de datos, solo los primeros números que vale la pena analizar (y los restantes son entendidos por pocas personas, y mis preguntas sobre esas pocas personas sobre ellos a menudo dan como resultado explicaciones conflictivas):

MemTotal:         395144 kB
MemFree:          184936 kB
Buffers:             880 kB
Cached:            84104 kB
SwapCached:            0 kB

MemTotal es la cantidad total de memoria disponible para el kernel y el espacio de usuario (a menudo menos que la RAM física real del dispositivo, ya que parte de esa RAM es necesaria para la radio, los búferes DMA, etc.).

MemFree es la cantidad de RAM que no se utiliza en absoluto. El número que ves aquí es muy alto; Por lo general, en un sistema Android, esto sería solo unos pocos MB, ya que intentamos usar la memoria disponible para mantener los procesos en ejecución.

Cached es la memoria RAM que se utiliza para las memorias caché del sistema de archivos y otras cosas similares. Los sistemas típicos necesitarán tener aproximadamente 20 MB para que esto evite estados de paginación incorrectos; el Android out of memory killer está sintonizado para un sistema en particular para asegurarse de que los procesos en segundo plano se eliminen antes de que la memoria RAM almacenada en caché se consuma demasiado para dar lugar a dicha paginación.







memory-management