Analiza seguimientos de forma masiva

Una vez que hayas recopilado varios seguimientos con ProfilingManager, explorarlos de forma individual para encontrar problemas de rendimiento se vuelve poco práctico. El análisis de seguimiento masivo te permite consultar un conjunto de datos de seguimientos de forma simultánea para lo siguiente:

  • Identificar regresiones de rendimiento comunes
  • Calcula distribuciones estadísticas (por ejemplo, latencia P50, P90 y P99).
  • Encuentra patrones en varios seguimientos.
  • Encuentra seguimientos atípicos para comprender y depurar problemas de rendimiento.

En esta sección, se muestra cómo usar el procesador de seguimiento por lotes de Perfetto para Python para analizar las métricas de inicio en un conjunto de seguimientos almacenados de forma local y ubicar los seguimientos atípicos para un análisis más detallado.

Diseña la consulta

Primero, crea una consulta de PerfettoSQL que extraiga la métrica que quieres comparar. En el siguiente ejemplo, se mide la latencia de inicio controlada por la app desde activityStart hasta el primer fotograma renderizado (Choreographer#doFrame), como se muestra en la Figura 1.

Vista de línea de tiempo de un seguimiento, en la que se destaca la duración desde el evento activityStart hasta el primer evento Choreographer#doFrame.
Figura 1. Sección de seguimiento desde activityStart hasta el primer fotograma generado.
CREATE OR REPLACE PERFETTO FUNCTION find_slices(pattern STRING) RETURNS
TABLE (name STRING, ts LONG, dur LONG) AS
SELECT name,ts,dur FROM slice WHERE name GLOB $pattern;

CREATE OR REPLACE PERFETTO FUNCTION generate_start_to_end_slices(startSlicePattern STRING, endSlicePattern STRING, inclusive BOOL) RETURNS
TABLE(name STRING, ts LONG, dur LONG) AS
SELECT name, ts, MIN(startToEndDur) as dur
FROM
  (SELECT S.name as name, S.ts as ts, E.ts + IIF($inclusive, E.dur, 0) - S.ts as startToEndDur
  FROM find_slices($startSlicePattern) as S CROSS JOIN find_slices($endSlicePattern) as E
  WHERE startToEndDur > 0)
GROUP BY name, ts;

SELECT ts,name,dur from generate_start_to_end_slices('activityStart','*Choreographer#doFrame [0-9]*', true)

Puedes ejecutar la consulta en la IU de Perfetto y, luego, usar los resultados de la consulta para generar un segmento de depuración (figura 2) y visualizarlo en el cronograma (figura 3).

Panel de resultados de la consulta de la IU de Perfetto que muestra cómo crear un segmento de depuración para una consulta de inicio.
Figura 2: Crea un registro de depuración para una consulta de inicio.
Una vista de línea de tiempo en la IU de Perfetto que muestra un seguimiento de depuración generado para una consulta de inicio.
Figura 3: Se generó un seguimiento de depuración para una consulta de inicio.

Configura el entorno de Python

Instala Python en tu máquina local y sus bibliotecas requeridas:

pip install perfetto pandas plotly

Crea la secuencia de comandos de análisis de seguimiento masivo

En la siguiente secuencia de comandos de ejemplo, se ejecuta la consulta en varios seguimientos con BatchTraceProcessor de Python de Perfetto.

from perfetto.batch_trace_processor import BatchTraceProcessor
import glob
import plotly.express as px

# Collect all trace files in the local directory
traces = glob.glob('*.perfetto-trace')

if not traces:
    print("No .perfetto-trace files found in the current directory.")
    exit(1)

if __name__ == '__main__':
    # Process all traces in parallel to aggregate metrics across runs
    with BatchTraceProcessor(traces) as btp:
        query = """
        CREATE OR REPLACE PERFETTO FUNCTION find_slices(pattern STRING) RETURNS
        TABLE (name STRING, ts LONG, dur LONG) AS
        SELECT name,ts,dur FROM slice WHERE name GLOB $pattern;

        CREATE OR REPLACE PERFETTO FUNCTION generate_start_to_end_slices(startSlicePattern STRING, endSlicePattern STRING, inclusive BOOL) RETURNS
        TABLE(name STRING, ts LONG, dur LONG) AS
        SELECT name, ts, MIN(startToEndDur) as dur
        FROM
          (SELECT S.name as name, S.ts as ts, E.ts + IIF($inclusive, E.dur, 0) - S.ts as startToEndDur
          FROM find_slices($startSlicePattern) as S CROSS JOIN find_slices($endSlicePattern) as E
          WHERE startToEndDur > 0)
        GROUP BY name, ts;

        SELECT ts,name,dur / 1000000 as dur_ms from generate_start_to_end_slices('activityStart','*Choreographer#doFrame [0-9]*', true)
        """
        df = btp.query_and_flatten(query)
        # Plot the distribution of startup times, tracking trace file paths on
        # hover
        violin = px.violin(df, x='dur_ms', hover_data='_path', title='startup time', points='all')
        violin.show()

Comprende la secuencia de comandos

Cuando ejecutas la secuencia de comandos de Python, se realizan las siguientes acciones:

  1. La secuencia de comandos busca en tu directorio local todos los registros de Perfetto con el sufijo .perfetto-trace y los usa como registros de origen para el análisis.
  2. Ejecuta una consulta de seguimiento masivo que calcula el subconjunto del tiempo de inicio correspondiente al tiempo desde el segmento de seguimiento activityStart hasta el primer fotograma que genera tu app.
  3. Traza la latencia en milisegundos con un diagrama de violín para visualizar la distribución de los tiempos de inicio.

Interpretar los resultados

Un diagrama de violín que muestra la distribución de las latencias de inicio consultadas.
Figura 4: Diagrama de violín de las latencias de inicio consultadas.

Cuando se ejecuta la secuencia de comandos, se genera un diagrama de violín que muestra una distribución bimodal con dos picos de latencia distintos (figura 4). Coloca el cursor sobre los datos individuales del gráfico para inspeccionar el nombre de archivo _path y comparar los seguimientos de cada pico (figura 5):

  • Seguimientos de alta latencia (pico derecho): Cuando se abre un seguimiento de este grupo en la IU de Perfetto, se muestra un segmento MyFlaggedFeature adicional que se ejecuta durante el inicio (figura 6).
  • Seguimientos de baja latencia (pico izquierdo): Abrir un seguimiento del grupo más rápido confirma que MyFlaggedFeature no está presente (figura 7), lo que indica que una marca de función habilitada para un subconjunto de usuarios causó la regresión de inicio.
Un gráfico que destaca un seguimiento de latencia alta.
Figura 5: Punto de datos de alta latencia en un diagrama de violín.
Un registro de seguimiento que destaca el inicio de alta latencia debido a la porción MyFlaggedFeature.
Figura 6: Inicio de seguimiento de latencia alta con un segmento MyFlaggedFeature adicional
Un seguimiento que destaca el inicio de baja latencia sin la porción MyFlaggedFeature.
Figura 7. Inicio de seguimiento de baja latencia

En este ejemplo, se muestra una de las muchas formas en que puedes usar el análisis de seguimiento masivo. Otros casos de uso incluyen extraer estadísticas del campo para medir el impacto, detectar regresiones y mucho más.