Документация Python неофициальный перевод
Содержание страницы

profiling – профилировщики Pythonprofiling – Python profilers

Добавлено в версии 3.15.

Исходный код: Lib/profiling/


Введение в профилированиеIntroduction to profiling

A profile is a set of statistics that describes how often and for how long various parts of a program execute. These statistics help identify performance bottlenecks and guide optimization efforts. Python provides two fundamentally different approaches to collecting this information: statistical sampling and deterministic tracing.

Пакет profiling объединяет встроенные инструменты профилирования Python в едином пространстве имён. Он содержит два подмодуля, каждый из которых реализует свой метод профилирования:

profiling.sampling

Статистический профилировщик, который периодически делает выборки стека вызовов. Можно запускать скрипты напрямую или подключаться к работающим процессам по PID. Предоставляет множество форматов вывода (flame graphs, heatmaps, Firefox Profiler), анализ GIL, отслеживание GC и несколько режимов профилирования (реальное время, процессор, GIL) практически без накладных расходов.

profiling.tracing

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

Примечание

Модули профилировщика предназначены для получения профиля выполнения программы, а не для бенчмаркинга. Для бенчмаркинга используйте модуль timeit, который обеспечивает достаточно точные измерения времени. Это различие особенно важно при сравнении кода Python с кодом на C: детерминированные профилировщики добавляют накладные расходы для кода Python, но не для функций уровня C, что может исказить сравнение.

Выбор профилировщикаChoosing a profiler

Для большинства задач анализа производительности используйте статистический профилировщик (profiling.sampling). Он имеет минимальные накладные расходы, работает как в разработке, так и в production, и предоставляет богатые возможности визуализации, включая флейм-графы, тепловые карты, анализ GIL и другое.

Используйте детерминированный профилировщик (profiling.tracing), когда вам нужны точные значения количества вызовов и нельзя пропустить ни одного вызова функции. Поскольку он инструментирует каждый вызов и возврат, он захватит даже очень быстрые функции, которые завершаются между интервалами выборки. Плата за это – более высокие накладные расходы.

В следующей таблице приведены ключевые различия:

Возможность

Статистическая выборка (profiling.sampling)

Детерминированный (profiling.tracing)

Накладные расходы

Практически отсутствуют

Умеренные

Точность

Статистическая оценка

Точное количество вызовов

Форматы вывода

pstats, флейм-граф, тепловая карта, gecko, свёрнутый

pstats

Режимы профилирования

Реальное время, процессор, GIL

Реальное время

Специальные кадры

GC, нативный (расширения C)

Н/Д

Подключение к PID

Да

Нет

Когда использовать статистическую выборкуWhen to use statistical sampling

Статистический профилировщик (profiling.sampling) рекомендуется для большинства задач анализа производительности. Используйте его так же, как profiling.tracing:

python -m profiling.sampling run script.py

Одна из главных сильных сторон профилировщика на основе выборки – разнообразие форматов вывода. Помимо традиционных таблиц pstats, он может создавать интерактивные флейм-графы, визуализирующие иерархии вызовов, построчные тепловые карты исходного кода, показывающие, где именно тратится время, и вывод для Firefox Profiler для анализа на временной шкале.

Профилировщик также позволяет заглянуть во внутреннее поведение интерпретатора Python, которое недоступно при детерминированном профилировании. Используйте --mode gil для выявления конкуренции за GIL в многопоточном коде, --mode cpu для измерения реального времени процессора без учёта ожидания ввода-вывода, или проверяйте кадры <GC>, чтобы понять накладные расходы на сборку мусора. Опция --native показывает время, затраченное в расширениях C, помогая отличить накладные расходы Python от производительности библиотек.

Для многопоточных приложений опция -a выполняет выборку всех потоков одновременно, показывая, как распределяется работа. А для отладки в production команда attach подключается к любому работающему процессу Python по PID без необходимости перезапуска или изменения кода.

Когда использовать детерминированную трассировкуWhen to use deterministic tracing

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

Основная причина выбрать детерминированную трассировку – необходимость точного подсчёта вызовов. Статистическое профилирование оценивает частоту на основе выборки, что может недооценивать короткоживущие функции, которые завершаются между выборками. Если требуется проверить, что оптимизация действительно уменьшила количество вызовов функций, или проследить полный граф вызовов, чтобы понять отношения вызывающих и вызываемых функций, детерминированная трассировка – правильный выбор.

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

Быстрый стартQuick start

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

Статистическое профилированиеStatistical profiling

Чтобы профилировать скрипт, используйте модуль profiling.sampling с командой run:

python -m profiling.sampling run script.py
python -m profiling.sampling run -m mypackage.module

Это запускает скрипт под профилировщиком и выводит сводку о том, где было потрачено время. Для интерактивного графа пламени:

python -m profiling.sampling run --flamegraph script.py

Чтобы профилировать уже запущенный процесс, используйте команду attach с идентификатором процесса:

python -m profiling.sampling attach 1234

Для настраиваемых параметров укажите интервал выборки (в микросекундах) и длительность (в секундах):

python -m profiling.sampling run -i 50 -d 30 script.py

Детерминированное профилированиеDeterministic profiling

Чтобы профилировать скрипт из командной строки:

python -m profiling.tracing script.py

Чтобы профилировать фрагмент кода программно:

import profiling.tracing
profiling.tracing.run('my_function()')

Это выполняет заданный код под профилировщиком и выводит сводку, показывающую точное количество вызовов функций и время.

Понимание вывода профилировщикаUnderstanding profile output

Оба профилировщика собирают статистику на уровне функций, хотя представляют её в разных форматах. Профилировщик на основе выборки предлагает несколько визуализаций (графы пламени, тепловые карты, Firefox Profiler, таблицы pstats), в то время как детерминированный профилировщик создаёт вывод, совместимый с pstats. Независимо от формата, основные концепции одинаковы.

Ключевые концепции профилирования:

Прямое время (также называется собственным временем или tottime)

Время, потраченное на выполнение кода в самой функции, за исключением времени, затраченного в вызванных ею функциях. Высокое прямое время указывает на то, что функция содержит дорогостоящие операции.

Совокупное время (также называется общим временем или cumtime)

Время, потраченное в функции и всех вызванных ею функциях. Это измеряет общую стоимость вызова функции, включая всё поддерево вызовов.

Количество вызовов (также называется ncalls или выборки)

Сколько раз функция была вызвана (детерминированное) или попала в выборку (статистическое). При детерминированном профилировании это точное значение. При статистическом профилировании оно представляет количество раз, когда функция появилась в стековой выборке.

Примитивные вызовы

Вызовы, которые не вызваны рекурсией. Когда функция рекурсивна, общее количество вызовов включает рекурсивные вызовы, но примитивные вызовы учитывают только первоначальный вход. Отображается как total/primitive (например, 3/1 означает три общих вызова, один примитивный).

Отношения вызывающих и вызываемых функций

Какие функции вызывали данную функцию (вызывающие) и какие функции она вызывала (вызываемые). Графы пламени визуализируют это в виде вложенных прямоугольников; pstats может отобразить это с помощью методов print_callers() и print_callees().

Совместимость с предыдущими версиямиLegacy compatibility

Для обратной совместимости модуль cProfile остаётся доступным как псевдоним для profiling.tracing. Существующий код, использующий import cProfile, будет продолжать работать без изменений во всех будущих версиях Python.

Устарело с версии 3.15: Чистый Python модуль profile устарел и будет удалён в Python 3.17. Вместо него используйте profiling.tracing (или его псевдоним cProfile). См. profile для руководства по миграции.

См. также

profiling.sampling

Статистический профилировщик на основе выборки с графами пламени, тепловыми картами и анализом GIL. Рекомендован для большинства пользователей.

profiling.tracing

Детерминированный трассирующий профайлер для точного подсчёта вызовов.

pstats

Анализ статистики и форматирование данных профилирования.

timeit

Модуль для измерения времени выполнения небольших фрагментов кода.

Подмодули