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

Puedes registrar varios tipos de perfiles de rendimiento en Android. La recopilación de un perfil te ayuda a depurar problemas relacionados con la velocidad de ejecución de tu app, la cantidad de memoria que usa, la cantidad de 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 registro del sistema

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 latencia, bloqueos, memoria, 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 el usuario. Los eventos controlados por código son eventos que los usuarios pueden activar a través de llamadas a funciones.

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

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:

  • Diagnosticar 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 perfiles basados en muestras, no proporcionan la información de sincronización que proporcionan los registros del sistema.

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

  • Diagnosticar problemas de contención de bloqueo. Con 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) causan retrasos en los recorridos del usuario.

  • Comprender el subprocesamiento múltiple en tu app. Los registros ofrecen una vista de varios subprocesos, que muestra el estado de cada subproceso y los segmentos de registro agregados por el sistema o tu app. Esta vista de subprocesos múltiples te ayuda a comprender qué subprocesos están activos, inactivos 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, incluidos la latencia, la memoria y el uso de 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 datos de registro en métricas personalizadas
  • Crear registros de depuración a partir de consultas para facilitar la visualización de lo que más te interesa en la IU de Perfetto
  • Realizar análisis complejos directamente en la IU de Perfetto

Perfiles de muestra de pila

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

Los perfiles de muestra de pila funcionan registrando muestras de ejecución de código y almacenando 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:

  • Optimizar los puntos de acceso. Las muestras de pila ayudan a identificar partes de tu código con mucha actividad de CPU, lo que significa que el subproceso suele estar en estado "en ejecución".
  • Comprender la ejecución del código. Las muestras de pila pueden ayudarte a comprender el comportamiento general de tu base de código.
  • Identificar el código que no se debe ejecutar. Es posible que encuentres pilas de llamadas que no debían ejecutarse, 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ó el volcado.

Te recomendamos que recopiles volcados de montón para hacer lo siguiente:

  • Descubrir objetos duplicados. Los volcados de montón muestran la cantidad de objetos activos, lo que es útil para hacer un seguimiento de los objetos duplicados. También proporcionan referencias de objetos, lo que te ayuda a identificar la ubicación del código en la que se crearon los objetos.
  • Encontrar 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.
  • Identificar 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 del montón vienen en versiones nativas y de Java, y son excelentes para depurar problemas de memoria. Son similares a las muestras de pila de llamadas, pero, en lugar de medir los ciclos de CPU, toman muestras cuando se asigna memoria.

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

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

Combinar perfiles

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

Ten en cuenta estas situaciones en las que combinar perfiles es beneficioso:

  • Situación 1: Investigar código no instrumentado. Un registro del sistema podría 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 el registro agregando más segmentos de registro.

  • Situación 2: Analizar fugas 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 del 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 optimizables con el almacenamiento en caché podría evitar que se produzcan GC.