¿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 obtengo también la memoria libre del teléfono?
java
android
memory
memory-management
Andrea Baccega
fuente
fuente
Respuestas:
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 interpretes correctamente los números que obtienes son extremadamente bajas. (Casi siempre que miro los números de uso de memoria con otros ingenieros, siempre hay una larga discusión sobre lo que realmente significan que solo da como resultado una conclusión vaga).
Nota: ahora tenemos una documentación mucho más extensa sobre la administració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 probablemente leer la última parte de este artículo que tiene una discusión sobre cómo se administra la memoria en Android:
Cambios de API de servicio que comienzan con Android 2.0
Ahora
ActivityManager.getMemoryInfo()
es nuestra API de más alto nivel para observar el uso general de la memoria. Esto está principalmente allí 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 sin procesar del nivel del núcleo 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:
Pero en cuanto a cuál es la diferencia entre
Pss
,PrivateDirty
ySharedDirty
... bueno ahora comienza la diversión.En realidad, se comparte mucha memoria en Android (y en los sistemas Linux en general) en múltiples procesos. Entonces, cuánta memoria usa un proceso realmente no está claro. Agregue además 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 asignar toda la RAM física asignada a cada proceso y sumar todos los procesos, probablemente terminaría con un número mucho mayor que la RAM total real.
El
Pss
número es una métrica que calcula el kernel que tiene en cuenta el uso compartido de memoria: básicamente, cada página de RAM en un proceso se escala por 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 RAM que estará disponible para el sistema cuando ese proceso desaparezca (y probablemente se incorpore rápidamente en cachés y otros usos).Eso es más o menos las API de SDK para esto. Sin embargo, hay más que puede hacer como desarrollador con su dispositivo.
Utilizando
adb
, hay mucha información que puede obtener sobre el uso de memoria de un sistema en ejecución. Uno común es el comandoadb shell dumpsys meminfo
que arrojará 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 pid de un solo proceso para ver, por ejemplo,adb shell dumpsys meminfo system
darme el proceso del sistema:La sección superior es la principal, donde
size
está el tamaño total en el espacio de direcciones de un montón en particular,allocated
es el kb de asignaciones reales que el montón cree que tiene,free
es el kb restante libre que el montón tiene para asignaciones adicionales,pss
ypriv dirty
son iguales como se discutió antes, específico para las páginas asociadas con cada uno de los montones.Si solo quiere ver el uso de memoria en todos los procesos, puede usar el comando
adb shell procrank
. La salida de esto en el mismo sistema se ve así:Aquí las columnas
Vss
yRss
son básicamente ruido (estos son el espacio de direcciones directo y el uso de RAM de un proceso, donde si sumas el uso de RAM en los procesos obtienes un número ridículamente grande).Pss
es como hemos visto antes, yUss
esPriv Dirty
.Algo interesante a tener en cuenta aquí:
Pss
yUss
son ligeramente (o más que ligeramente) diferentes de lo que vimos enmeminfo
. ¿Porqué es eso? Bueno, procrank utiliza un mecanismo de kernel diferente para recopilar sus datos que el quememinfo
hace, y dan resultados ligeramente diferentes. ¿Porqué es eso? Sinceramente, no tengo ni idea. Creo queprocrank
puede ser el más preciso ... pero realmente, esto solo deja el punto: "toma cualquier información de memoria que obtengas con un grano de sal; a menudo un grano muy grande".Finalmente está el comando
adb shell cat /proc/meminfo
que da un resumen del uso general de la memoria del sistema. Aquí hay una gran cantidad de datos, solo los primeros números que vale la pena discutir (y los restantes son entendidos por pocas personas, y mis preguntas sobre esas pocas personas sobre ellos a menudo resultan en explicaciones contradictorias):MemTotal
es la cantidad total de memoria disponible para el kernel y el espacio del usuario (a menudo menos que la RAM física real del dispositivo, ya que parte de esa RAM es necesaria para la radio, las memorias intermedias DMA, etc.).MemFree
es la cantidad de RAM que no se usa en absoluto. El número que ves aquí es muy alto; normalmente en un sistema Android, esto sería solo unos pocos MB, ya que intentamos usar la memoria disponible para mantener los procesos en ejecuciónCached
es la RAM que se usa para cachés del sistema de archivos y otras cosas similares. Los sistemas típicos necesitarán tener 20 MB más o menos para evitar que entren en mal estado de paginación; El asesino de Android sin memoria está sintonizado para un sistema en particular para asegurarse de que los procesos en segundo plano se eliminen antes de que la RAM en caché se consuma demasiado como para dar como resultado tal paginación.fuente
Sí, puede obtener información de la memoria mediante programación y decidir si desea realizar un trabajo intensivo en memoria.
Obtenga VM Heap Size llamando a:
Obtenga memoria de máquina virtual asignada llamando a:
Obtenga VM Heap Size Limit llamando al:
Obtenga memoria asignada nativa llamando a:
Hice una aplicación para descubrir el comportamiento 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
fuente
Este es un trabajo en progreso, pero esto es lo que no entiendo:
¿Por qué no se asigna el PID al resultado en activityManager.getProcessMemoryInfo ()? Claramente, desea que los datos resultantes sean significativos, entonces, ¿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 te dice con qué pids están asociados. Si simplemente pasa una matriz de todos los pids, no tendrá forma de comprender los resultados. Según entiendo su uso, no tiene sentido pasar más de un pedido a la vez, y si ese es el caso, ¿por qué hacerlo de modo que activityManager.getProcessMemoryInfo () solo tome una matriz int?
fuente
Hackbod's es una de las mejores respuestas en Stack Overflow. Arroja luz sobre un tema muy oscuro. Me ayudó mucho.
Otro recurso realmente útil es este video imperdible: Google I / O 2011: administración de memoria para aplicaciones de Android
ACTUALIZAR:
Estadísticas del proceso, un servicio para descubrir cómo su aplicación administra la memoria explicada en la publicación del blog Estadísticas del proceso: Comprender cómo su aplicación usa RAM por Dianne Hackborn:
fuente
Android Studio 0.8.10+ ha introducido una herramienta increíblemente útil llamada Memory Monitor .
Para qué es bueno:
Figura 1. Forzar un evento GC (Recolección de basura) en Android Memory Monitor
Puede usar mucha información buena sobre el consumo de RAM en tiempo real de su aplicación.
fuente
1) Supongo que no, al menos no de Java.
2)
fuente
Descubrimos que todas las formas estándar de obtener la memoria total del proceso actual tienen algunos problemas.
Runtime.getRuntime().totalMemory()
: solo devuelve memoria JVMActivityManager.getMemoryInfo()
,Process.getFreeMemory()
y cualquier otra cosa basada en/proc/meminfo
: devuelve información de memoria sobre todos los procesos combinados (por ejemplo, android_util_Process.cpp )Debug.getNativeHeapAllocatedSize()
- usosmallinfo()
que devuelven información sobre asignaciones de memoria realizadas pormalloc()
y solo funciones relacionadas (ver android_os_Debug.cpp )Debug.getMemoryInfo()
- hace el trabajo pero es demasiado lento. Tarda unos 200 ms en Nexus 6 para una sola llamada. La sobrecarga de rendimiento hace que esta función sea inútil para nosotros, ya que la llamamos regularmente y cada llamada es bastante notable (consulte android_os_Debug.cpp )ActivityManager.getProcessMemoryInfo(int[])
- llamadasDebug.getMemoryInfo()
internas (ver ActivityManagerService.java )Finalmente, terminamos usando el siguiente código:
Devuelve VmRSS métrica. Puede encontrar más detalles al respecto aquí: uno , dos y tres .
PD: Me di cuenta de que el tema aún carece de un fragmento de código real y simple de cómo estimar el uso de memoria privada del proceso si el rendimiento no es un requisito crítico:
fuente
En Android Studio 3.0, han introducido Android-Profiler para ayudarlo a comprender cómo su aplicación utiliza recursos de CPU, memoria, red y batería.
https://developer.android.com/studio/profile/android-profiler
fuente
Hay muchas respuestas anteriores que definitivamente lo ayudarán, pero (después de 2 días de pagar e investigar sobre las herramientas de memoria adb) creo que puedo ayudar con mi opinión .
Como dice Hackbod: Por lo tanto, si tomara toda la RAM física realmente asignada a cada proceso y sumara todos los procesos, probablemente terminaría con un número mucho mayor que la RAM total real. así que no hay forma de que pueda obtener la cantidad exacta de memoria por proceso.
Pero puedes acercarte a él por alguna lógica ... y te diré cómo ...
En primer lugar, debe ser un usuario root para que funcione. Ingrese a la consola con privilegio de root ejecutando
su
en proceso y obtenga suoutput and input stream
. Luego paseid\n
(enter) en nuestro flujo de salida y escríbalo en la salida del proceso. Si obtendrá un flujo de entrada que contengauid=0
, usted es usuario root.Ahora aquí está la lógica que usará en el proceso anterior
Cuando obtiene el flujo de salida del proceso, pasa el comando (procrank, dumpsys meminfo, etc.) en
\n
lugar de id y obtieneinputstream
y lee, almacena el flujo en bytes [], char [], etc., utiliza datos sin procesar ... y usted ¡¡¡¡¡están hechos!!!!!permiso:
Comprueba si eres usuario root:
Ejecute su comando con
su
logcat:
Esto es solo un intento, sugiérame si me perdí algo
fuente