Red de conocimiento informático - Material del sitio web - Cómo comprobar el uso de memoria de las aplicaciones de Android

Cómo comprobar el uso de memoria de las aplicaciones de Android

Análisis de mensajes de registro

La forma más sencilla de investigar el uso de memoria de una aplicación es mirar los mensajes de registro de Dalvik. Estos mensajes de registro se pueden encontrar en logcat (el resultado se puede ver en Device Monitor o IDE como Eclipse y Android Studio). Cada vez que se produce una recolección de basura, logcat imprime un mensaje de registro que contiene la siguiente información:

Java

1

D/dalvikvm: lt;GC_Reasongt;lt ; Cantidad_freedgt;, lt;Heap_statsgt;, lt.External_memory_statsgt;. External_memory_statsgt;, lt;Pause_timegt;

Motivo del GC

El motivo para activar la recolección de basura y el tipo de recolección de basura. Las causas incluyen:

GC_CONCURRENT

Recolección de basura simultánea, que se activa cuando el montón comienza a llenarse para liberar memoria.

GC_FOR_MALLOC

El montón está lleno y la recolección de basura se activa cuando la aplicación intenta asignar memoria. En este momento, el sistema debe pausar la aplicación para reclamar la memoria.

GC_HPROF_DUMP_HEAP

Cree un archivo HPROF para analizar la recolección de basura activada por la aplicación.

GC_EXPLICIT

Recolección de basura explícita, por ejemplo, activada cuando se llama a gc() (se deben evitar las llamadas manuales y, en su lugar, dejar que el recolector de basura llame de forma proactiva cuando sea necesario).

GC_EXTERNAL_ALLOC

Esto solo ocurre en API 10 y versiones inferiores (la memoria en versiones más nuevas solo se asigna en el montón de Dalvik). Recupere la memoria asignada externamente (como los datos de píxeles almacenados en la memoria local o los buffers de bytes NIO).

Número de liberaciones

La cantidad de memoria liberada después de la recolección de basura.

Estado del montón

Porcentaje de inactividad y (número de objetos activos)/(tamaño total del montón).

Estado de la memoria externa

En API 10 y versiones inferiores, memoria asignada externamente (tamaño de memoria asignada) / (valor límite cuando se produce el reciclaje).

Tiempo de pausa

Cuanto mayor sea el montón, mayor será el tiempo de pausa. El tiempo de pausa de recopilación concurrente se divide en dos partes: una al comienzo de la recopilación y la otra cerca del final de la recopilación.

Por ejemplo:

Java

1

D/dalvikvm(9050): gc_CONCURRENT liberó 2049K, 65 liberó 3571K/9991K, externo 4703K/5261K, en pausa 2 ms 2 ms

A medida que estos mensajes de registro aumentan, tenga en cuenta el cambio en el estado del montón (3571K/9991K en el ejemplo anterior). Si el valor continúa aumentando sin disminuir, puede haber una pérdida de memoria.

Buscar actualizaciones del montón

Para comprender el tipo y el momento del uso de la memoria de la aplicación, puede buscar actualizaciones en tiempo real del montón de aplicaciones en Device Monitor:

1. Abra Monitor de dispositivo.

Carga la utilidad de monitor desde la ruta lt;sdkgt;/tools/.

2. En la ventana del monitor de depuración, seleccione el proceso de aplicación que desea ver en la lista de procesos de la izquierda.

3. Haga clic en Actualizar montón encima de la lista de procesos.

4. Seleccione la pestaña Montón en el panel derecho.

La vista del montón muestra el estado básico del uso de la memoria del montón y se actualiza después de cada recolección de basura. Para ver el estado de la actualización, haga clic en el botón Gause GC.

Figura 1. Herramienta Device Monitor que muestra los botones [1] Update Heap y [2] Cause GC. La pestaña Montones a la derecha muestra los montones.

Seguimiento de las asignaciones de memoria

Cuando se trata de reducir los problemas de memoria, debe utilizar un rastreador de asignaciones para comprender mejor dónde la asignan los acaparadores de memoria.

Por ejemplo, el seguimiento de las asignaciones de memoria a medida que se desplaza por una lista en su aplicación le permite ver cómo se ven realmente las asignaciones de memoria, incluidos qué subprocesos están asignando memoria y dónde. Esto es útil para optimizar las rutas del código para reducir el esfuerzo y mejorar la fluidez de la interfaz de usuario.

Para utilizar el rastreador de asignación:

1 Abra Device Monitor.

Cargue las herramientas de monitorización desde la ruta lt;sdkgt;/tools/.

2. En la ventana DDMS, seleccione el proceso de solicitud en el panel izquierdo.

3. Seleccione la pestaña "Asignar rastreadores" en el panel derecho.

4. Haga clic en "Iniciar seguimiento". Ejecute la aplicación en la ruta del código a analizar.

6. Haga clic en Obtener asignaciones para actualizar la lista de asignaciones.

La lista muestra todas las asignaciones actuales y buffers circulares (tamaño limitado a 512). Haga clic en una fila para ver la información de seguimiento de la pila de la asignación. La pila muestra no sólo el tipo de objeto asignado, sino también a qué subproceso, clase, archivo y línea pertenece el objeto asignado.

Figura 2. La herramienta Device Monitor muestra la asignación de memoria de la aplicación actual y el seguimiento de la pila en Allocation Tracker.

Nota: Siempre habrá algunas asignaciones provenientes de DdmVmInternal y del propio rastreador de asignaciones.

Aunque no es necesario (ni posible) eliminar todo el código que afecta gravemente al rendimiento, el rastreador de asignación puede ayudar a localizar problemas graves en su código. Por ejemplo, una aplicación podría crear un nuevo objeto Paint con cada operación de pintura. Cambiar este objeto a una variable global es una modificación muy simple para mejorar el rendimiento.

Ver la asignación de memoria general

Para analizar más a fondo y ver la asignación de diferentes tipos de memoria en la memoria de la aplicación, utilice el siguiente comando adb:

Java p>

1

adb shell dumpsys meminfo lt; package_namegt )

Genera una lista de las asignaciones de memoria actuales de la aplicación en kilobytes.

Al visualizar esta información, debe estar familiarizado con los siguientes tipos de asignación:

Memoria privada (limpia y sucia)

Memoria exclusiva de un proceso . Esta es la cantidad de memoria que el sistema puede recuperar directamente cuando se destruye el proceso de la aplicación. En términos generales, la memoria "privada sucia" es la parte más importante de la memoria, ya que solo la utiliza su propio proceso. Solo se almacena en la memoria y, por lo tanto, no se puede paginar en la memoria externa (Android no admite el intercambio). Todo el montón Dalvik y el montón local asignados son memoria "privada sucia"; la parte del montón Dalvik y el montón local que el proceso Zygote disfrutó es memoria sucia disfrutó.

Uso de memoria física (PSS)

Esta es otra forma de calcular el uso de memoria de la aplicación; cuenta las páginas disfrutadas en todos los procesos. A cualquier página que ocupe memoria exclusivamente se le calculará su valor PSS directamente, mientras que a las páginas que se disfrutan intensamente con otros procesos se les calculará su valor PSS en proporción al disfrute sexual.

Por ejemplo, una página compartida por dos procesos tendría la mitad de su tamaño calculado en el PPS de cada proceso.

Un beneficio del método de cálculo de PSS es que al sumar los valores de PSS de todos los procesos, se puede determinar la huella de memoria total de todos los procesos. Esto significa que usar PSS es una buena manera de calcular el uso de memoria real de un proceso, comparar el uso de memoria entre procesos y el tamaño total de memoria restante.

Por ejemplo, aquí se muestra el resultado del proceso de Gmail en una tableta. Muestra mucha información, pero explica específicamente algunas de las claves que se enumeran a continuación.

Nota: La información que realmente ve puede diferir ligeramente de lo que ve aquí, y los detalles del resultado también pueden variar dependiendo de la versión de la plataforma.

Java

1

2

3

4

5

5

p>

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

p>

** MEMINFO en pid 9953 [com.google.android.gm] **

Pss Pss Compartir Privado Compartir Privado Montón Montón Montón Montón Montón

Total Clean 126

Dalvik Montón 5110(3) 0 4136 4988(3) 0 0 0 9168 8958(6) 210

Dalvik Otros 2850 0 2684 2772 0 0 0

Pila 36 0 8 36 0 0

Cursor 136 0 0 136 0 0

Ashmem 12 0 28 0 0 0 0

Otro desarrollador 380 0 24 376 0 4

.so mmap 5443(5) 1996 2584 2664(5) 5788 1996(5)

. apk mmap 235 32 0 0 1252 32

.ttf mmap 36 12 0 0 88 12

.dex mmap 3019(5) 2148 0 0 8936 2148(5)

Otro mmap 107 0 8 8 324 68

Desconocido 6994(4) 0 252 6992(4) 0 0 0

TOTAL 24358(1) 4188 9724 17972(2) 16388 4260(2) 16968 16595 336

Objetos

Vistas: 426 ViewRootImpl: 3(8)

AppContexts: 6(7) Actividad.

2(7)

Activos: 2 AssetManagers: 2

Carpetas locales: 64 Carpetas proxy: 34

Destinatarios por fallecimiento: 0

Socket OpenSSL: 1

SQL

MEMORY_USED: 1739

PAGECACHE_OVERFLOW: 1164 MALLOC_SIZE: 62

Normalmente, solo debes preocuparte por la columna Pss Total y la columna Privado Sucio. En algunos casos, las columnas Private Clean y Heap Alloc también pueden proporcionar información muy útil. A continuación se muestran algunos tipos de asignación de memoria que debe considerar (los tipos enumerados en las filas):

Dalvik Heap

La memoria utilizada por las asignaciones Dalvik de su aplicación. Pss Total contiene todas las asignaciones de Zygote (que disfrutan de ponderación entre procesos como se indica en la definición de PSS anterior). Private Dirty es el tamaño de la memoria exclusiva del montón de la aplicación, que consta de porciones asignadas individualmente y páginas de memoria asignadas por Zygote que se modifican cuando el proceso de la aplicación replica la división de Zygote.

NOTA: Las versiones más nuevas de la plataforma cuentan con Dalvik Other. pss Total y Private Dirty en el montón de Dalvik no incluyen los gastos generales de Dalvik, como la compilación justo a tiempo (JIT) y la recolección de basura (GC), mientras que las versiones anteriores incluían los gastos generales de Dalvik.

Heap Alloc es el tamaño del montón Dalvik y del montón local asignado a la aplicación. Su valor es mayor que Pss Total y Private Dirty porque el proceso se copia y divide de Zygote y contiene la parte asignada que disfruta el proceso ***.

.so mmap y .dex mmap

mmap asigna la memoria utilizada por el código .so (nativo) y .dex (Dalvik). Pss Total contiene código de plataforma que se puede disfrutar en todas las aplicaciones; Private Clean es un código específico de la aplicación. Normalmente, el tamaño de la memoria asignada real es mayor; el tamaño de la memoria que se muestra aquí es el tamaño de la memoria utilizada por la aplicación después de realizar la operación actual. Sin embargo, la suciedad privada de .so mmap es mayor porque ya se ha asignado espacio de memoria para la dirección final del código nativo cuando se carga.

Desconocidas

Páginas de memoria que no se pueden clasificar en otros proyectos. Actualmente, esta sección consta principalmente de la mayoría de las asignaciones locales, es decir, las partes que no se pueden calcular debido a la aleatorización del diseño del espacio de direcciones (ASLR) cuando la herramienta recopila los datos. Al igual que el montón de Dalvik, Pss Total in Unknown cuenta la porción compartida con Zygote***, mientras que Private Dirty in Unknown cuenta solo la memoria utilizada individualmente por la aplicación.

Total

La memoria real total utilizada por el proceso (PSS) es la suma de todas las entradas de PSS anteriores. Representa el uso total de memoria de un proceso y se puede utilizar para comparación directa con otros procesos o con la memoria total disponible.

Private Dirty y Private Clean son la cantidad total de memoria ocupada solo por el proceso y no se comparten con otros procesos.

Cuando se destruye un proceso, la memoria que ocupa (especialmente la memoria sucia privada) se devolverá al sistema. La memoria sucia se refiere a páginas de memoria que han sido modificadas, por lo que deben residir en la memoria (porque no hay intercambio); Limpiar memoria se refiere a una página de memoria que ha sido asignada para ser utilizada por un archivo persistente (por ejemplo, para ejecutar código) para que pueda intercambiarse si no se usa temporalmente.

Vídeo

ViewRootImpl

El número de vistas raíz activas en el proceso. Cada vista raíz está asociada con una ventana, por lo que ayuda a identificar pérdidas de memoria que involucran ventanas y cuadros de diálogo.

Contextos y actividades de la aplicación

El número de objetos de contexto y actividad que residen actualmente en el proceso. Identifique rápidamente objetos de actividad con fugas comunes que no se pueden recolectar como basura debido a referencias estáticas. Estos objetos suelen tener muchas otras asignaciones asociadas, por lo que esta es una buena forma de rastrear grandes pérdidas de memoria.

Nota: Los objetos View y Drawable también contienen referencias a la Actividad en la que se encuentran, por lo que mantener los objetos View o Drawable también causará fugas de actividad en la aplicación.

Obtener un volcado de montón

Un volcado de montón es una instantánea de todos los objetos en el montón de la aplicación, almacenada como un archivo binario HPROF. Los volcados de montón de aplicaciones proporcionan un estado general del montón de aplicaciones, por lo que al ver las actualizaciones del montón puede rastrear problemas que puedan haberse descubierto.

Recuperar un volcado de montón:

1. Abra Device Monitor.

Cargue las herramientas de monitorización desde la ruta lt;sdkgt;/tools/.

2. En la ventana DDMS, seleccione el proceso de solicitud en el panel izquierdo.

3. Haga clic en Volcar archivo HPROF, como se muestra en la Figura 3.

4. En la ventana emergente, asigne un nombre al archivo HPROF, seleccione la ubicación de almacenamiento y haga clic en Guardar.

Figura 3. La herramienta Device Monitor muestra el botón [1] Volcar archivo HPROF.

Si necesita un volcado de montón que localice con mayor precisión el problema, puede llamar a dumpHprofData() en el código de su aplicación para generar un volcado de montón.

El formato de un volcado de montón es esencialmente el mismo que el de un archivo Java HPROF, pero no es idéntico. La principal diferencia con los volcados de montón de Android es que muchas asignaciones de memoria ocurren dentro del proceso Zygote. Sin embargo, debido a que las asignaciones de memoria de Zygote son compartidas por todos los procesos de la aplicación, estas asignaciones de memoria son menos relevantes para el análisis del montón de aplicaciones.

Para analizar un volcado de montón, necesita una herramienta estándar como jhat o Eclipse Memory Analysis Tool (MAT). Por supuesto, el primer paso que debe hacer es convertir el archivo HPROF del formato de archivo de Android al formato de archivo J2SE HRPOF. Puede hacer esto usando la herramienta hprof-conv que se encuentra en lt;sdkgt;/platform-tools/ ruta. Usar hprof-conv es muy simple, simplemente ingrese dos parámetros: el archivo HPROF original y la ubicación del archivo HPROF convertido. Por ejemplo:

Java

1

hprof-conv heap-original.hprof heap-converted.hprof

NOTA: Si utilizar Si el DDMS está integrado con Eclipse, ¡no es necesario volver a realizar la operación de conversión HPROF! --Se han convertido los valores predeterminados.

El archivo HPROF convertido ahora se puede cargar en MAT u otras herramientas de análisis de montón que puedan analizar el formato J2SE HPROF.

Al analizar el montón de aplicaciones, debe buscar pérdidas de memoria causadas por:

Referencias a largo plazo a Actividad, Contexto, Vista, Dibujable y posiblemente referencias a Actividad u otros objetos a los que hace referencia el contenedor de contexto

Clases internas no estáticas (por ejemplo, un Runnable que contiene una actividad o un contenedor de contexto)

Pérdida de memoria, Runnable, que contiene una instancia de actividad de un Runnable)

Almacenamiento en caché innecesario de objetos a largo plazo

Uso de la herramienta de análisis de memoria de Eclipse

La herramienta de análisis de memoria de Eclipse (MAT) es un análisis de montón herramienta Herramienta de volcado. Es una herramienta bastante poderosa con capacidades que van mucho más allá del alcance de este documento, por lo que esto es sólo una introducción.

Abra el archivo HPROF de tipo convertido en MAT y verá un gráfico circular en la pantalla de descripción general que muestra los objetos más grandes que ocupan el montón. Hay varios enlaces funcionales debajo del gráfico:

La vista de histograma muestra una lista de todas las clases y el número de instancias de cada clase.

Por lo general, debe determinar el número de instancias de una clase y utilizar esta vista para encontrar otras instancias de la clase. Por ejemplo, una filtración de código fuente común es tener instancias adicionales de la clase Actividad, cuando el enfoque correcto es tener solo una instancia a la vez. Para buscar instancias de una clase específica, ingrese el nombre de la clase en el campo en la parte superior de la lista para encontrarla.

Si hay demasiadas instancias de una clase, haga clic derecho y seleccione "Listar objetos", en la lista que aparece, haciendo clic derecho y seleccionando "Ruta a la raíz de GC". identificar instancias retenidas.

El árbol Dominator es una lista de objetos mostrados por tamaño de montón reservado.

Los objetos a tener en cuenta son aquellos cuya porción reservada del tamaño del montón es aproximadamente igual al tamaño de la fuga observada a través de registros de GC, actualizaciones del montón o rastreadores de asignación.

Cuando vea un elemento sospechoso, haga clic derecho y seleccione Ruta a GC Rootsgt; excluir referencias débiles. Se abrirá una nueva pestaña con una lista de referencias a objetos con presuntas fugas.

Nota: la mayoría de las aplicaciones mostrarán instancias de recursos cerca de la parte superior de las grandes porciones del montón en el gráfico circular, pero esto generalmente se debe a que hay muchos recursos en la ruta res/ utilizada en el solicitud.

La Figura 4.MAT muestra la vista del histograma y los resultados de la búsqueda de "MainActivity".

Para obtener más información sobre MAT, mire la charla de Google I/O 2011 "Administración de memoria para aplicaciones de Android", que tiene una charla práctica sobre MAT aproximadamente a las 21:10. Consulte también la documentación del Analizador de memoria de Eclipse.

Comparación de volcados de montón

Para comprender cómo han cambiado las asignaciones de memoria, es útil comparar el estado del montón de una aplicación en diferentes momentos. Se pueden comparar dos volcados de montón usando MAT:

1. Obtenga dos archivos HPROF como se describe anteriormente, consulte la sección Obtención de volcados de montón.

2. Abra el primer archivo HPROF en MAT (archivo gt; abra el volcado del montón).

3.En la vista Historial de navegación (si no está visible, seleccione Ventana>Historial de navegación), haga clic derecho en el histograma y seleccione Agregar a la cesta de comparación.

4.Abra el segundo archivo HRPOF y repita los pasos 2 y 3.

5.Cambie a la vista de cesta de comparación y haga clic en el resultado de la comparación (icono rojo "!").

Provocar pérdidas de memoria

Mientras utilizas las herramientas anteriores, también debes realizar una prueba de esfuerzo del código de la aplicación para intentar reproducir la pérdida de memoria. Una forma de comprobar posibles pérdidas de memoria en su aplicación es ejecutarla durante un tiempo antes de comprobar el montón. La memoria perdida alcanzará lentamente el límite superior del tamaño del montón asignado. Por supuesto, cuanto más pequeña sea la fuga, más tiempo necesitará ejecutar la aplicación para reproducirla.

Las pérdidas de memoria también se pueden desencadenar de las siguientes maneras:

1. Operaciones repetidas de cambio de pantalla horizontal y vertical en diferentes estados activos. Girar la pantalla puede hacer que la aplicación pierda objetos Actividad, Contexto o Vista porque el sistema recrea la actividad y no puede reciclar estos objetos si la aplicación contiene referencias a ellos en otro lugar.

2. Cambie de aplicación en diferentes estados activos (cambie a la pantalla de inicio y luego vuelva a la aplicación).

Consejo: También puedes utilizar pruebas con monos para realizar los pasos anteriores. Para obtener más información sobre cómo ejecutar pruebas de monos, consulte la documentación de Monkeyrunner.