Анализ следов веществ в больших объемах

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

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

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

Составьте запрос

Первым шагом для проведения массового анализа является создание запроса 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

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

Приведенный ниже пример скрипта выполняет запрос в нескольких трассировках, используя Python BatchTraceProcessor из библиотеки Perfetto .

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

traces = glob.glob('*.perfetto-trace')

if __name__ == '__main__':
    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)

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

Далее найдите разницу между двумя группами данных. Это поможет вам более детально изучить отдельные трассы. В этом примере график настроен таким образом, что при наведении курсора на точки данных (задержки) можно определить имена файлов трасс. Затем вы можете открыть одну из трасс, входящих в группу с высокой задержкой.

При открытии трассировки из группы с высокой задержкой (рис. 5) вы обнаружите дополнительный фрагмент с именем MyFlaggedFeature , работающий во время запуска (рис. 6). Напротив, выбор трассировки из группы с более низкой задержкой (самый левый пик) подтверждает отсутствие этого же фрагмента (рис. 7). Это сравнение указывает на то, что определенный флаг функции, включенный для подгруппы пользователей, запускает регрессию.

На графике выделен участок с высокой задержкой.
Рисунок 5. Точка данных с высокой задержкой на скрипичном графике.
Трассировка, демонстрирующая высокую задержку при запуске из-за среза MyFlaggedFeature.
Рисунок 6. Трассировка запуска с высокой задержкой и дополнительным фрагментом `MyFlaggedFeature`.
Трассировка, демонстрирующая низкую задержку при запуске без использования фрагмента MyFlaggedFeature.
Рисунок 7. Трассировка запуска с низкой задержкой.

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