Tipos de perfiles y cuándo es útil cada uno

En Android, puedes registrar varios tipos de perfiles de rendimiento. Recopilar un perfil te ayuda a depurar problemas relacionados con la velocidad de ejecución de tu app, la cantidad de memoria que usa, la batería que consume y mucho más.

En este documento, se describen los tipos de perfiles más útiles y cuándo usar cada uno para depurar problemas de rendimiento comunes.

Registros del sistema

Ejemplo de registro del sistema
Figura 1: Ejemplo de System Trace.

Un registro del sistema es un perfil potente que contiene información sobre procesos, subprocesos, información de sincronización, ejecución de CPU y tareas, y eventos definidos por el sistema o el usuario.

Desde la perspectiva de una app, la naturaleza de la información en los registros puede abarcar una amplia variedad de áreas, como la latencia, el jank, la memoria, la batería y mucho más.

Los registros del sistema contienen los siguientes eventos controlados por código que pueden ser definidos por el sistema o por el usuario. Los eventos basados en código son eventos que los usuarios pueden activar a través de llamadas a funciones.

  • Segmentos de seguimiento: Representan el tiempo entre diferentes puntos de tu código. Se pueden agregar con las APIs de Trace.beginSection y Trace.endSection.
  • Contadores de seguimiento: Son valores numéricos que representan métricas, por ejemplo, el tamaño del montón. Se pueden agregar con la API de Trace.setCounter.

Los registros del sistema también contienen métricas que se pueden crear a partir de consultas de PerfettoSQL y que se pueden usar para realizar análisis o comparar registros.

Te recomendamos que uses los registros del sistema para realizar las siguientes tareas:

  • Diagnostica problemas de latencia. Los registros del sistema son excelentes para encontrar problemas de latencia causados por retrasos, esperas o problemas de programación. Otros generadores de perfiles, como los basados en muestras, no proporcionan la información de sincronización que sí proporcionan los registros del sistema.

  • Encuentra cálculos duplicados. El registro puede revelar si se repiten ciertos cálculos, lo que podría indicar operaciones innecesarias.

  • Diagnostica problemas de contención de bloqueo. Con la información sobre los estados de los subprocesos y los segmentos que muestran cuándo se bloquean los recursos, puedes identificar si los bloqueos (como los bloques synchronized) están causando demoras en los recorridos del usuario.

  • Comprende el procesamiento de subprocesos múltiples en tu app. Los registros ofrecen una vista de varios subprocesos, en la que se muestra el estado de cada uno y los segmentos de registro que agregó el sistema o tu app. Esta vista de subprocesos múltiples te ayuda a comprender qué subprocesos están activos, en suspensión o qué están ejecutando, y cómo interactúan.

  • Realizar análisis de rendimiento complejos La potente interfaz de usuario y la capacidad de mostrar varios tipos de información hacen que los registros del sistema sean útiles para depurar una amplia variedad de problemas de rendimiento, como la latencia, la memoria y el uso de la batería.

Los registros del sistema también admiten consultas con PerfettoSQL. Esta potente función te permite hacer lo siguiente:

  • Extraer datos específicos
  • Transformar los datos de registro en métricas personalizadas
  • Crea pistas de depuración a partir de consultas para visualizar más fácilmente lo que más te interesa en la IU de Perfetto.
  • Realiza análisis complejos directamente en la IU de Perfetto.

Perfiles de muestras de pila

Ejemplo de perfil de muestra de pila
Figura 2.: Ejemplo de perfil de muestra de pila.

Los perfiles de muestra de pila registran muestras de la ejecución del código y almacenan la información de la pila de llamadas a una velocidad establecida mientras un subproceso ejecuta tareas en la CPU. Esto proporciona estadísticas sobre lo que hace tu código durante la ejecución.

Te recomendamos que uses muestras de pila para hacer lo siguiente:

  • Optimiza los puntos de acceso. Las muestras de pila ayudan a identificar las partes del código con mucha actividad de la CPU, lo que significa que el subproceso suele estar en estado "en ejecución".
  • Comprende la ejecución del código. Las muestras de pila pueden ayudarte a comprender el comportamiento general de tu base de código.
  • Identifica el código que no se debe ejecutar. Es posible que encuentres pilas de llamadas que no deberían haberse ejecutado, lo que indica oportunidades inmediatas de optimización.

Volcados de montón

Ejemplo de volcado de montón
Figura 3: Ejemplo de volcado de montón.

Los volcados de montón de Java muestran una instantánea de la memoria del montón de Java de tu app. Esta instantánea incluye todos los objetos y cómo se refieren entre sí en el momento en que se tomó la volcado.

Te recomendamos que recopiles volcados de memoria para hacer lo siguiente:

  • Descubre objetos duplicados. Los volcados de montón muestran la cantidad de objetos activos, lo que resulta útil para hacer un seguimiento de los objetos duplicados. También proporcionan referencias a objetos, lo que te ayuda a identificar la ubicación del código en la que se crearon los objetos.
  • Encuentra fugas de memoria. Los volcados de montón pueden revelar memoria que ya no debería estar en uso cuando se tomó el volcado, lo que indica posibles fugas de memoria.
  • Identifica los objetos que se podrían optimizar. Al mostrar los objetos que usan mucha memoria y sus recuentos, los volcados de montón ayudan a identificar patrones de uso de memoria ineficientes.

Perfiles del montón

Ejemplo de perfil del montón
Figura 4: Ejemplo de perfil del montón.

Los perfiles de montón están disponibles en versiones nativas y de Java, y son excelentes para depurar problemas de memoria. Son similares a las muestras de la pila de llamadas, pero, en lugar de medir los ciclos de CPU, toman muestras cuando se asigna memoria.

Te recomendamos que uses perfiles de montón para lograr lo siguiente:

  • Reduce la saturación de la memoria. Los perfiles de montón proporcionan muestras con ubicaciones de código para las asignaciones de memoria. Esto te ayuda a identificar las áreas que crean muchos objetos temporales, lo que puede contribuir a la recolección de elementos no utilizados (GC) frecuente en tu app.
  • Descubre las fugas de memoria. Los perfiles de montón se pueden usar con otros perfiles de memoria para diagnosticar y corregir fugas de memoria. Te ayudan a identificar las ubicaciones que asignan mucha más memoria de la esperada.

Cómo combinar perfiles

A menudo, analizarás el rendimiento con un solo perfil. Sin embargo, recopilar varios perfiles o un solo perfil combinado a menudo puede proporcionar una imagen más completa y ayudar a diagnosticar problemas complejos que un solo perfil no puede.

Considera estas situaciones en las que combinar perfiles es beneficioso:

  • Situación 1: Investigación de código sin instrumentar. Un registro del sistema puede mostrar latencia para las operaciones que ya instrumentaste. Sin embargo, es posible que necesites más información sobre las partes no instrumentadas de tu código que se ejecutan durante esos períodos. Para investigar, toma un perfil de pila de llamadas para comprender el código ejecutado. Esta información puede ayudarte a mejorar tu seguimiento agregando más segmentos de registro.

  • Situación 2: Análisis de pérdidas de memoria y recolecciones de elementos no utilizados. Imagina que un registro del sistema muestra un aumento constante en la memoria del montón de Java debido a las asignaciones, lo que activa recolecciones de elementos no utilizados (GC) frecuentes. Para comprender los objetos asignados, toma un perfil de montón o un volcado de montón. Este enfoque combinado te ayuda a identificar formas de reducir el uso de memoria. Por ejemplo, reducir las asignaciones innecesarias o que se pueden optimizar con el almacenamiento en caché podría evitar que se produzcan recolecciones de basura.