DDMS de Android: una guía para la consola definitiva de Android

Publicado: 2022-03-11

El desarrollo es un negocio complicado. El objetivo sigue moviéndose, nuevas tecnologías y dominios cobran vida periódicamente, surgen nuevas herramientas de vez en cuando y los idiomas cambian en lo que parece ser un caos controlado.

Aún así, incluso con todos estos cambios, las reglas fundamentales siguen siendo las mismas. Una de las más importantes de estas reglas subyacentes establece que para crear un software realmente increíble, debe obtener una introspección profunda, continua y detallada en su sistema de ejecución. Diagnóstico , depuración y generación de perfiles son términos que a veces se usan en este contexto, pero la regla es más profunda. Un desarrollador de primer nivel literalmente "siente" su sistema. Él sabe que lo que causará es la espera de que se libere más memoria, lo que hará que sus subprocesos se agoten en la CPU, cuyas acciones resultarán en E/S extensas o acceso a la red, por lo tanto, ralentizarán toda su operación.

Realmente no hay forma de evitarlo. Podría ser un desarrollador muy inteligente que escribe un código increíble, pero, hasta que no tenga la habilidad anterior, es decir, ser capaz de monitorear y estudiar los detalles del comportamiento del tiempo de ejecución de su sistema, aún fallará cuando se trata de entregar realmente de primera categoría. aplicaciones

De hecho, después de adquirir algo de experiencia, detectará toda una categoría de "enfermedades del código" que se pueden atribuir al descuido de la regla de la introspección: En pocas palabras, escribir código (a veces código inteligente) sin un seguimiento continuo de sus efectos en la plataforma real. .

DDMS en Android: mi arma preferida para la introspección

Afortunadamente para nosotros, la comunidad de Android había logrado ofrecer tantas herramientas de introspección de primer nivel. Stetho de Facebook se encuentra entre los mejores, ARO ("Optimizador de recursos de aplicaciones") de AT&T es un poco más antiguo pero aún de primera categoría, con probablemente la mejor consola de monitoreo de red que existe, mientras que LeakCanary adopta un enfoque mucho más limitado, concentrándose (y lo hace muy bien en it) en la biblioteca de detección de fugas de memoria en tiempo de ejecución. Para resumir, no hay escasez de herramientas de depuración de Android.

Aún así, el diamante de la corona, la herramienta de introspección en la que confiar cuando se necesita extraer datos cruciales, precisos y bien formateados con respecto al comportamiento en tiempo de ejecución de su aplicación, sigue siendo el viejo Dalvik Debug Monitor Server (DDMS) en Android Studio, que ha estado con nosotros (por desgracia, infrautilizado por tantos equipos) desde los días del complemento Eclipse de Android.

¿Qué importancia tiene DDMS en el desarrollo de Android? Bueno, sabiendo lo que sé ahora sobre DDMS y el monitoreo de aplicaciones móviles en general, digamos hace 5 o 6 años, como desarrollador de Android con menos experiencia, me habría ahorrado muchos dolores de cabeza y noches de depuración.

Ilustración de portada de Android DDMS: Depuración de desarrolladores con DDMS.

¡Y es que DDMS es tan fácil de dominar!

Por supuesto, una gran parte de su uso correcto, como con cualquier otra herramienta de software, viene con la experiencia. Debe perfeccionar sus habilidades profesionales durante un tiempo hasta que se vuelva realmente bueno en el monitoreo del rendimiento en tiempo de ejecución. Pero incluso en cuestión de horas, digamos después de leer este artículo, si sigue mis sugerencias y las aplica en su próxima aplicación, ¡los resultados serán increíbles! Perfilar y ajustar incluso sistemas complejos no es tan difícil. ¡También puede ser divertido!

A menudo se hace una pregunta con respecto a la diferencia entre los desarrolladores móviles novatos y los de nivel maestro. Dominar DDMS en Android, o en términos generales, la creación de perfiles de aplicaciones y las capacidades de introspección, es una de esas diferencias importantes.

Nota: una parte importante de convertirse en un desarrollador de primer nivel es usar las mejores bibliotecas disponibles en su dominio. En un artículo anterior de Toptal, enumeré algunas de las mejores bibliotecas para desarrolladores disponibles para Android. En cierto sentido, este artículo es una continuación del artículo de la "biblioteca" y cubre una de las muchas herramientas de Android. No hace falta decir que si desea mejorar sus habilidades de desarrollador de Android, ¡léalo ahora!

Una guía rápida de DDMS en Android Studio

Y ahora, sin más preámbulos, profundicemos en la descripción de DDMS, una de las mejores herramientas para desarrolladores de Android.

Al comparar el esfuerzo con el beneficio, probablemente ninguna otra herramienta pueda mejorar la calidad de su aplicación y ayudarlo a localizar los errores realmente complicados y esquivos que pueda contener. Pero aún así, por alguna razón (pereza, ¿alguien?), Muchos equipos no usan DDMS.

Comencemos con un curso intensivo en DDMS:

Se puede acceder a DDMS a través de Studio > Tools > Android > Android Device Monitor y haciendo clic en el botón DDMS en el menú. También puedes colocarlo como icono de acceso directo (Sí, acepto) en tu panel superior.

Una vez abierto, esto es lo que verá:

Captura de pantalla: Acceso a DDMS a través de Android Device Monitor

El panel izquierdo permite la selección de dispositivos/aplicaciones y la consola derecha le brinda múltiples vistas, cada una en su propia pestaña, cada una mostrando una vista específica de su aplicación.

Los principales servicios proporcionados por Dalvik Debug Monitor Server son:

  • Estadísticas de uso de la memoria de la aplicación (estadísticas de asignación de objetos y almacenamiento dinámico total)
  • Estadísticas de subprocesos de la aplicación
  • Captura de pantalla del dispositivo
  • Explorador de archivos del dispositivo
  • Falsificación de llamadas entrantes y SMS
  • Falsificación de datos de ubicación
  • Logcat

Para obtener el valor actual de la memoria en montón que utiliza su aplicación, simplemente haga lo siguiente:

  • Conecte el dispositivo en el que se ejecuta su aplicación
  • Haga clic en el botón Actualizar montón para habilitar la recopilación de estadísticas de montón
  • Abra la pestaña Montón
  • Haga clic en "Cause GC" para forzar una ejecución de GC. Solo después de dicha ejecución comenzará la recopilación de datos del montón.
  • Mantenga la pestaña abierta, continúe trabajando en su aplicación y vuelva a hacer clic periódicamente en "Cause GC" para actualizar los datos de estadísticas del montón.

Esta última línea probablemente requiere una explicación adicional. El uso de la memoria es uno de esos valores analíticos donde su dinámica es mucho más importante que el valor inicial. Para la mayoría de las aplicaciones, no nos importará mucho el valor de uso del almacenamiento dinámico inicial. Nos preocuparemos mucho por el progreso de este valor, ya que nos proporcionará una clara indicación de una de las verdaderas pesadillas que aguardan a los desarrolladores móviles: las fugas de memoria de Android:

Captura de pantalla: los datos del montón se utilizan para identificar una fuga de memoria de Android en DDMS

Mi uso del módulo heap stat es simple; como parte del ciclo de vida del desarrollo de la aplicación, después de introducir cambios que deberían afectar el uso del almacenamiento dinámico, activaré el módulo, "Causar GC" para iniciar la recopilación de estadísticas, activar (generalmente más de una vez) las posiciones intensivas del almacenamiento dinámico de mi aplicación, y periódicamente "Causa GC" para actualizar. Si el uso del montón sigue creciendo, tengo una pérdida de memoria en mis manos y necesito resolverlo (detalles sobre cómo, a continuación). Si no, e independientemente del tamaño real del montón, estoy bien.

Si se detecta una fuga de memoria, la siguiente herramienta que usaré es el Rastreador de asignación de objetos. Veamos qué puede hacer por la gestión de la memoria en Android.

Rastreador de asignación de objetos

El rastreador de asignaciones, en pocas palabras, le proporcionará la información necesaria para averiguar quién es el "culpable" del tamaño actual del almacenamiento dinámico. Este módulo le dirá de qué hilos y métodos provienen los comandos de asignación en tiempo real, lo que lo hace invaluable para el análisis de memoria en Android.

Para comenzar el seguimiento, haga lo siguiente:

  • Seleccione el dispositivo/proceso relevante como antes
  • Cambie a la pestaña Rastreador de asignación y haga clic en Iniciar seguimiento para comenzar.
  • A partir de aquí, se realizará un seguimiento de todas las asignaciones nuevas.
  • Haga clic en "Obtener asignaciones" para obtener una vista de lista de todas las asignaciones más recientes (las más recientes desde el último "comienzo")
  • Para saber quién es la autoridad de asignación, haga clic en una línea específica de la lista

Rastreador de asignación de objetos en DDMS, interfaz de usuario

Ahora, según mi propia experiencia, realizar acciones de asignación intensiva en su aplicación y luego hacer clic en "Obtener asignaciones" para ver los contadores de asignación generalmente lo dirigirá a la fuga de una manera directa; a veces, cuando la fuga no es lineal (es decir, ocurre de vez en cuando) O cuando su aplicación contiene varias fugas que podrían no funcionar. En tales casos, y no he encontrado muchos de estos, deberá recurrir a la creación manual de un archivo HPROF de volcado y analizarlo. El análisis de la memoria y la gestión de la memoria de Android no se tratarán en profundidad en este artículo. Vea aquí algunas pistas.

Consola de información de subprocesos: el uso de la CPU de Android es más fácil

Bien conocido por cualquier desarrollador, las rutas síncronas de lógica de ejecución se agrupan en subprocesos, cada uno de los cuales constituye un flujo de ejecución en serie dentro de su aplicación. Literalmente, todas las aplicaciones usan más de un solo hilo de ejecución. Algunos de ellos usan docenas.

Un examen general de los problemas potenciales cuando se usan subprocesos está fuera del alcance de este artículo. Concentrémonos entonces en uno solo, a saber, la inanición de subprocesos, que es el principal problema por el que visitaría la consola de información de subprocesos.

En todas las aplicaciones móviles, diferentes subprocesos competirán por el tiempo de CPU. Simplemente no hay suficientes de esos para todos. ¿Qué sucede si, por alguna razón, uno o más de estos subprocesos no obtienen el tiempo de ejecución que necesitan? Normalmente cosas malas. El sistema no se comportará como usted planeó que se comportara, lo que siempre es una mala idea. Las posibles razones de este problema podrían ser establecer una prioridad baja, otros subprocesos ejecutándose simultáneamente con una prioridad demasiado alta, pasar mucho tiempo en los monitores de sincronización y más. Todo notoriamente difícil de detectar solo mediante la revisión del código.

¡Consola de subprocesos Android DDMS al rescate!

Consola de información de subprocesos en DDMS, interfaz de usuario

Al ingresar a la vista de hilos, verá una lista compuesta por registros de hilos, cada uno de los cuales contiene el nombre y el ID del hilo, y dos contadores adicionales llamados utime y stime. Utime mide el tiempo total invertido por el subproceso en ejecutar el código de usuario (piense en sus funciones y bibliotecas de terceros), mientras que stime mide el tiempo total invertido en el código del sistema (reposo, sincronización, llamadas al sistema, mucho). El pprimero, utime, generalmente será más interesante para nosotros, aunque puedo pensar en problemas que se manifestarán principalmente por el contador de stime.

Bien, tenemos nuestro código ejecutándose, incluidos varios subprocesos, y queremos asegurarnos de que todos nuestros subprocesos obtengan su parte del tiempo de CPU. Para esto, primero dejamos que nuestro sistema funcione por un tiempo, y luego abrimos la pestaña del hilo y comenzamos a buscar valores de tiempo de uso "peculiares". Cero ciertamente puede representar un problema: el subproceso literalmente no obtuvo tiempo de CPU ni uso de CPU. Pero los valores demasiado altos pueden representar un aspecto diferente del mismo problema: a saber, subprocesos cuya prioridad es tan alta que hace que otros se mueran de hambre.

Tenga en cuenta que para un tipo de subprocesos, un valor de tiempo de ejecución cero o casi cero no indicará un problema real. Estos son los subprocesos enlazados de E/S, subprocesos que en su mayoría realizan acceso a redes o discos (o bases de datos). Estos subprocesos deberían pasar la mayor parte de su tiempo esperando que lleguen los datos o bloqueando las llamadas al sistema pendientes, ninguna de estas acciones aumenta el contador de tiempo de uso. ¡Conoce tus hilos!

Sugerencia: nunca use el nombre predeterminado del hilo. No significa nada y, por lo general, no podrá detectarlo en las vistas de DDMS. en cambio, cada vez que cree un hilo o lo obtenga de un grupo de hilos, comience su interacción asignándole un nombre que se explique por sí mismo. Esto hará que su vida sea mucho más fácil que depurar/perfilar su sistema. Por lo general, antepongo el nombre de la aplicación para distinguir entre el hilo generado por Android y los generados por mi propio código, por ejemplo: MyApp-server-connector, MyApp-db-interactor, etc.

Sugerencia: la prioridad de un subproceso indica (en términos generales) la cantidad de tiempo de CPU que le otorgará el planificador. La prioridad asignada a sus subprocesos de trabajo es de vital importancia para el rendimiento general y la "suavidad" de su aplicación y, en muchos casos, puede ser la diferencia entre un comportamiento rápido y fluido y uno lento y accidentado. La regla aquí es simple: la prioridad predeterminada asignada por Android, que es NORMAL = 5, casi siempre no es la que desea usar. En cambio, para la mayoría de los subprocesos de trabajo, desea un impacto mucho menor en el uso general de la CPU. Para hacer esto, al inicio de un subproceso, establezca su prioridad en un valor menor, generalmente voy con prioridad = 3.

Consola de estadísticas de red

Las estadísticas de red consisten en permitirle monitorear los canales de comunicación entrantes y salientes de su aplicación de una manera razonablemente legible por humanos.

El eje y en el gráfico de red representa la velocidad de transferencia de la transmisión medida en KB/segundo, mientras que el eje x representa el tiempo transcurrido en segundos. Por lo tanto, para obtener una estimación rápida del tamaño de la transmisión, trate de estimar el área del pico relevante. Después de un tiempo, esto se vuelve bastante fácil.

Tenga en cuenta que, después de ingresar a esta consola, deberá hacer clic en el botón superior "habilitar" para que comiencen a aparecer las mediciones de red.

Antes de que la consola de red hubiera madurado hasta el nivel en el que se encuentra ahora, los desarrolladores generalmente tenían que recurrir al uso de aplicaciones rastreadoras (algunos todavía lo hacen) para obtener información similar.

Lo mejor de esta consola es la forma en que visualiza uno de los principales comportamientos de agotamiento de la batería: la comunicación continua en paquetes pequeños. Como muchos de ustedes saben, lo que hará que su aplicación agote la batería no son los cinco minutos de red intensiva que hace, sino los largos períodos de red breve y repetitiva, por ejemplo, para mantener vivo, diagnóstico o actualizaciones de estado.

Una vez que se detecta un patrón de este tipo, y la pantalla de paquetes visuales de la consola de red lo hace muy fácil, piense de inmediato en el procesamiento por lotes. ¿Puedo agrupar varias transmisiones pequeñas en una sola grande? ¡El impacto en la batería de este cambio seguramente hará que las aplicaciones pasen de ser un consumidor de batería a una categoría de buen comportamiento!

Consola de estadísticas de red en DDMS

Sugerencia: nunca cargue una imagen en la memoria tal como está. Este es un bloqueo por falta de memoria que está a punto de ocurrir. En su lugar, realice una carga reducida, o incluso mejor, use una biblioteca de terceros para administrar la escala por usted.

Aunque rara vez usará esta información, tenga en cuenta que el DDMS se basa en la pila Android Debug Bridge (ADB) para pasar datos de vuelta/desde el dispositivo. Si el DDMS no muestra su aplicación o se congela en medio de una sesión de DDMS, lo mejor que puede hacer es abrir una consola y escribir:

 adb devices

para asegurarse de que su dispositivo sea accesible y autorizado con ADB. Si no es el caso, en muchos casos, reiniciar su servidor ADB local debería resolver el problema:

 adb kill-server adb devices # restarts the adb server and displays all detected devices

Si aún tiene problemas y su aplicación está instalada en un dispositivo físico, intente desconectar todas las instancias del emulador. ¿Por qué? Debido a que DDMS se conecta a sí mismo tanto a dispositivos físicos como a instancias de emulador, el valor predeterminado es el último.

Ejemplo de uso de DDMS en la vida real: una aplicación se detiene (no falla, solo se detiene). El usuario se apresura inmediatamente a la estación de trabajo cercana, se conecta al USB y abre DDMS en la vista de subprocesos para encontrar la pila de subprocesos » subproceso fallido » seguimiento de la pila; en mi caso, debido a un punto muerto de sincronización que, una vez detectado, se resolvió fácilmente cambiando.

Sugerencia: si la memoria RAM estándar asignada a su aplicación por Android no es suficiente, como podría suceder, por ejemplo, con aplicaciones intensivas en medios, tenga en cuenta que puede obtener entre un 15 y un 20 % de memoria adicional en la mayoría de los dispositivos levantando el indicador de manifiesto _ largeHeap : https://developer.android.com/guide/topics/manifest/application-element.html_

Emulación de estado del dispositivo en Android DDMS

Como regla general, las aplicaciones móviles no son construcciones lineales. En cambio, implementan estrategias de conciencia que les permiten monitorear y reaccionar a los cambios en el estado del dispositivo. Una aplicación puede, por ejemplo, escuchar llamadas entrantes o mensajes de texto, puede realinear su estado de acuerdo con el estado de la red y puede rastrear y reaccionar ante cambios en la ubicación del dispositivo.

Un ejemplo trivial de esto último sería una aplicación de GPS. La mayoría de nosotros no desarrollamos este tipo de aplicaciones (por desgracia, el mercado no es lo suficientemente grande...) pero aún así, en muchos casos, implementamos la lógica, que depende de la ubicación, ya sea una simple vista de mapa de la posición actual del usuario, seguimiento de ruta , o una pantalla de datos sensible a la ubicación.

La prueba de tales condiciones sensibles al estado es notoriamente compleja, a veces más que escribir el código real. Si tienes un dispositivo físico con SIM puedes, por supuesto, emitir y recibir llamadas y SMS. Cambiar el estado de telefonía de su dispositivo es mucho más difícil, pero aún se puede hacer. Los cambios de ubicación de prueba pueden ser más complicados, aunque pasear por la ciudad con su computadora portátil es una opción...

Pero aún así, ¿cómo manejaríamos las instancias del emulador? ¿Cómo podemos probarlos para estos cambios?

Ejemplo de emulación de estado de dispositivo en DDMS

DDMS al rescate, una vez más. Una de las características más sólidas pero que a menudo se pasa por alto del DDMS es su capacidad para emitir eventos simulados ("falsos") en una instancia de emulador en ejecución. DDMS puede emitir una llamada desde un número específico al emulador, enviar un SMS, cambiar los datos de estado de la telefonía y más.

Una vez que lleguen al emulador, todos estos eventos falsificados ya no se distinguirán de los eventos "reales", es decir, como si los recibieran los sensores de hardware subyacentes. Específicamente, todos los receptores de su aplicación relevante se activarán de la misma manera que lo harían al recibir una llamada/mensaje SMS real.

Activar el estado de telefonía y las acciones es bastante sencillo:

Para probar su aplicación en casos de conectividad de red baja (lo que debería hacer en cualquier aplicación centrada en la red), vaya a la sección Estado de telefonía y establezca los valores de velocidad y latencia en los valores deseados. Por lo general, elijo el valor GPRS para ambos como una forma efectiva de emular una baja conectividad, pero siéntase libre de establecer sus propios valores.

Para simular llamadas telefónicas o SMS, vaya a la sección Acción de telefonía, configure el número de teléfono de origen, agregue un mensaje de texto si es necesario y dispare. Esta herramienta es especialmente efectiva cuando ha configurado una ruta de código dedicada para llamadas desde el extranjero y desea probarla dentro del presupuesto.

Las cosas se ponen más interesantes cuando se trata de burlarse de una nueva ubicación.

Si todo lo que desea es establecer una nueva ubicación para su instancia de emulador, elija Manual, configure los valores de latitud/longitud deseados y presione Enviar.

Controles de ubicación manual utilizados para la suplantación de identidad en DDMS

Pero, ¿qué sucede si, en lugar de establecer una ubicación fija, desea que su aplicación siga una ruta preestablecida, digamos, examine su comportamiento mientras el usuario viaja de una ciudad a otra? Tal prueba puede tener un gran valor para cualquier aplicación respaldada por mapas, así como para otras aplicaciones sensibles a la ubicación que configuran su ventana de datos por ubicación del usuario. Aquí, querrá ver que el cambio de ubicación a diferente velocidad mantendrá actualizada la ventana de datos mostrada.

Para ello, utilizaremos un formato especial llamado KML, que fue desarrollado específicamente para ser utilizado con Google Earth, y que representan rutas, o trayectos, como un conjunto de puntos conectados en el espacio, que pueden ser mediante dispositivos habilitados para GPS.

GPX es un formato de ruta alternativo compatible con DDMS. A todos los efectos prácticos, estos dos deben considerarse intercambiables cuando se utilizan para la suplantación de ubicación móvil.

Pasemos ahora por las etapas de configuración de una ruta simulada en el emulador.

  1. Crea una ruta. Con mucho, la forma más sencilla sería utilizar la opción de dirección de Google Maps para establecer el origen y el destino apropiados.

Suplantación de ubicación en DDMS con Google Maps

  1. Una vez que la ruta se muestra sobre el mapa, vaya a la línea de dirección y copie la URL

  2. Con la URL en el portapapeles, vaya al visualizador de GPS, péguela en el cuadro de texto "Proporcionar URL" y haga clic en el botón Convertir:

Suplantación de ubicación de DDMS: configuración de GPS Wisualizer

y haga clic para descargar el archivo GPX resultante (con un nombre algo desordenado, por ejemplo, 20170520030103-22192-data.gpx)

  1. Volviendo a DDMS Location Control, abra la pestaña GPX, haga clic en Cargar GPX y seleccione el archivo recién descargado

Importación de GPX en el control de ubicación de DDMS

  1. ¡Hemos terminado! Ahora puede navegar entre las diferentes ubicaciones de la ruta haciendo clic en los botones Atrás y Adelante, o haciendo clic en el botón Reproducir para recorrer automáticamente la ruta a una velocidad establecida.

No es necesario que cree su propia ruta. Un montón de rutas para descargar desde un sitio como OpenStreetMap (ver la sección 'Rastreos GPS').

Por último, tenga en cuenta que, a diferencia de las versiones anteriores de DDMS, en las que la carga de archivos de ruta era muy sencilla, las versiones más nuevas pueden requerir algunas pruebas y errores al cargar una ruta específica.

Por ejemplo, parece que DDMS solo admite GPX 1.1. Las nuevas versiones de GPX pueden requerir algún ajuste manual.

Además, el formato de waypoint GPX ya no es compatible. En su lugar, utilice el formato de pista GPX:

 <trk> <name /> <cmt /> <trkseg> <trkpt lat="27.0512" lon="-80.4324"> <ele>0</ele> <time>2017-02-02T08:01:41Z</time> </trkpt> </trkseg> </trk>

Depuración de Android: ¡una hora a la semana marca la diferencia!

¡Basta de teoría! Ahora es el momento para un poco de práctica. Sugiero, suponiendo que sea un desarrollador de Android, que a partir de su próximo proyecto dedique solo una hora a la semana para obtener una introspección sobre el rendimiento de su aplicación a través de DDMS.

¡Se sorprenderá de la cantidad de información de calidad (es decir, información que puede usarse para mejorar inmediatamente el estado de su aplicación) que esto le proporcionará!

Android DDMS, como he visto una y otra vez con los desarrolladores novatos, es una herramienta que puede mejorar en gran medida las capacidades de un desarrollador, siempre que se domine y se emplee correctamente. La capacidad de un desarrollador de Android para ofrecer sistemas de primer nivel aumentará literalmente uno o dos niveles una vez que aproveche todo el potencial de DDMS en el desarrollo de Android. Por lo tanto, reservar algunas horas para hacer un buen uso de DDMS parece una inversión inteligente, ya que puede mejorar en gran medida el rendimiento y la eficiencia de Android.

Sé uno de los chicos inteligentes. úsalo