Как анализировать трассировки в массовом порядке

Если вы собрали несколько трассировок с помощью ProfilingManager, изучать их по отдельности, чтобы найти проблемы с производительностью, нецелесообразно. Массовый анализ трассировок позволяет одновременно запрашивать набор данных трассировок, чтобы:

  • Выявлять распространенные регрессии производительности.
  • Рассчитывать статистические распределения (например, задержку P50, P90, P99).
  • Находить закономерности в нескольких трассировках.
  • Находите трассировки с выбросами, чтобы выявлять и устранять проблемы с производительностью.

В этом разделе рассказывается, как использовать Perfetto Python Batch Trace Processor для анализа показателей запуска в наборе локально сохраненных трассировок и поиска выбросов для более глубокого анализа.

Создание запроса

Сначала создайте запрос PerfettoSQL, который извлекает показатель, который вы хотите сравнить. В примере ниже показано, как измерить задержку при запуске, контролируемую приложением, от activityStart до первого обработанного кадра (Choreographer#doFrame), как показано на рисунке 1.

Временная шкала трассировки, на которой выделена продолжительность от события activityStart до первого события Choreographer#doFrame.
Рисунок 1. Раздел трассировки от activityStart до первого сгенерированного кадра.
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)

Вы можете выполнить запрос в интерфейсе Perfetto, а затем использовать результаты запроса, чтобы создать дорожку отладки (рис. 2) и визуализировать ее на временной шкале (рис. 3).

Панель результатов запроса в интерфейсе Perfetto, на которой показано, как создать отладочный трек для запроса запуска.
Рисунок 2. Создайте отладочную версию для запроса при запуске.
Временная шкала в интерфейсе Perfetto, на которой показан сгенерированный отладочный трек для запроса при запуске.
Рисунок 3. Создан отладочный трек для стартового запроса.

Настройте среду Python

Установите Python на локальный компьютер и необходимые библиотеки:

pip install perfetto pandas plotly

Создайте скрипт для массового анализа трассировки

Следующий пример скрипта выполняет запрос в нескольких трассировках с помощью BatchTraceProcessor для Python.

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()

Как работает скрипт

При запуске скрипта Python выполняются следующие действия:

  1. Скрипт ищет в локальном каталоге все трассировки Perfetto с суффиксом .perfetto-trace и использует их в качестве исходных трассировок для анализа.
  2. Он выполняет массовый запрос трассировки, который вычисляет подмножество времени запуска, соответствующее времени от фрагмента трассировки activityStart до первого кадра, сгенерированного вашим приложением.
  3. Задержка в миллисекундах отображается на скрипичной диаграмме, которая позволяет визуализировать распределение времени запуска.

Как интерпретировать результаты

Скрипичная диаграмма, показывающая распределение задержек при запуске.
Рисунок 4. Скрипичная диаграмма задержек при запуске.

При запуске скрипта создается скрипичная диаграмма, показывающая бимодальное распределение с двумя отдельными пиками задержки (рис. 4). Наведите указатель мыши на отдельные элементы данных на графике, чтобы проверить название файла _path и сравнить трассировки для каждого пика (рис. 5).

  • Трассировки с высокой задержкой (правый пик). Если открыть трассировку из этой группы в Perfetto UI, можно увидеть дополнительный фрагмент MyFlaggedFeature, который выполняется во время запуска (рис. 6).
  • Трассировки с низкой задержкой (левый пик). Открыв трассировку из более быстрой группы, мы видим, что MyFlaggedFeature отсутствует (рис. 7). Это указывает на то, что флаг функции, включенный для подгруппы пользователей, вызвал регрессию запуска.
График, на котором выделен след с высокой задержкой.
Рисунок 5. Элемент с высокой задержкой на скрипичной диаграмме.
Трассировка, показывающая высокую задержку при запуске из-за фрагмента MyFlaggedFeature.
Рисунок 6. Запуск отслеживания высокой задержки с дополнительным фрагментом MyFlaggedFeature.
Трассировка, показывающая запуск с низкой задержкой без фрагмента MyFlaggedFeature.
Рисунок 7. Запуск трассировки с низкой задержкой.

Это лишь один из множества способов использования массового анализа трассировки. Другие варианты использования включают извлечение статистики из поля для оценки воздействия, обнаружение регрессий и многое другое.