profiling.md
1> **Источник:** https://python-all.ru/3.16/library/profiling.html2>3> «Документация Python на русском» – неофициальный перевод официальной документации Python: версии от 2.6 до 3.16, полнотекстовый поиск, английский оригинал рядом с переводом. Эта Markdown-версия страницы предназначена для работы с LLM: вставьте её в ChatGPT, Claude или Cursor.45---67# `profiling` – профилировщики Python89Добавлено в версии 3.15.1011**Исходный код:** [Lib/profiling/](https://python-all.ru/src/main/Lib/profiling)1213---1415## Введение в профилирование1617A *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.1819Пакет `profiling` объединяет встроенные инструменты профилирования Python в едином пространстве имён. Он содержит два подмодуля, каждый из которых реализует свой метод профилирования:2021**[`profiling.sampling`](https://python-all.ru/3.16/library/profiling.sampling.html#module-profiling.sampling)**2223Статистический профилировщик, который периодически делает выборки стека вызовов. Можно запускать скрипты напрямую или подключаться к работающим процессам по PID. Предоставляет множество форматов вывода (flame graphs, heatmaps, Firefox Profiler), анализ GIL, отслеживание GC и несколько режимов профилирования (реальное время, процессор, GIL) практически без накладных расходов.2425**[`profiling.tracing`](https://python-all.ru/3.16/library/profiling.tracing.html#module-profiling.tracing)**2627Детерминированный профилировщик, который отслеживает каждый вызов функции, возврат и событие исключения. Предоставляет точное количество вызовов и точную информацию о времени, захватывая каждый вызов, включая очень быстрые функции.2829> **Примечание**30>31> Модули профилировщика предназначены для получения профиля выполнения программы, а не для бенчмаркинга. Для бенчмаркинга используйте модуль [`timeit`](https://python-all.ru/3.16/library/timeit.html#module-timeit), который обеспечивает достаточно точные измерения времени. Это различие особенно важно при сравнении кода Python с кодом на C: детерминированные профилировщики добавляют накладные расходы для кода Python, но не для функций уровня C, что может исказить сравнение.3233## Выбор профилировщика3435Для большинства задач анализа производительности используйте статистический профилировщик ([`profiling.sampling`](https://python-all.ru/3.16/library/profiling.sampling.html#module-profiling.sampling)). Он имеет минимальные накладные расходы, работает как в разработке, так и в production, и предоставляет богатые возможности визуализации, включая флейм-графы, тепловые карты, анализ GIL и другое.3637Используйте детерминированный профилировщик ([`profiling.tracing`](https://python-all.ru/3.16/library/profiling.tracing.html#module-profiling.tracing)), когда вам нужны **точные значения количества вызовов** и нельзя пропустить ни одного вызова функции. Поскольку он инструментирует каждый вызов и возврат, он захватит даже очень быстрые функции, которые завершаются между интервалами выборки. Плата за это – более высокие накладные расходы.3839В следующей таблице приведены ключевые различия:4041| Возможность | Статистическая выборка ([`profiling.sampling`](https://python-all.ru/3.16/library/profiling.sampling.html#module-profiling.sampling)) | Детерминированный ([`profiling.tracing`](https://python-all.ru/3.16/library/profiling.tracing.html#module-profiling.tracing)) |42| --- | --- | --- |43| **Накладные расходы** | Практически отсутствуют | Умеренные |44| **Точность** | Статистическая оценка | Точное количество вызовов |45| **Форматы вывода** | pstats, флейм-граф, тепловая карта, gecko, свёрнутый | pstats |46| **Режимы профилирования** | Реальное время, процессор, GIL | Реальное время |47| **Специальные кадры** | GC, нативный (расширения C) | Н/Д |48| **Подключение к PID** | Да | Нет |4950### Когда использовать статистическую выборку5152Статистический профилировщик ([`profiling.sampling`](https://python-all.ru/3.16/library/profiling.sampling.html#module-profiling.sampling)) рекомендуется для большинства задач анализа производительности. Используйте его так же, как [`profiling.tracing`](https://python-all.ru/3.16/library/profiling.tracing.html#module-profiling.tracing):5354```sh55python -m profiling.sampling run script.py56```5758Одна из главных сильных сторон профилировщика на основе выборки – разнообразие форматов вывода. Помимо традиционных таблиц pstats, он может создавать интерактивные флейм-графы, визуализирующие иерархии вызовов, построчные тепловые карты исходного кода, показывающие, где именно тратится время, и вывод для Firefox Profiler для анализа на временной шкале.5960Профилировщик также позволяет заглянуть во внутреннее поведение интерпретатора Python, которое недоступно при детерминированном профилировании. Используйте `--mode gil` для выявления конкуренции за GIL в многопоточном коде, `--mode cpu` для измерения реального времени процессора без учёта ожидания ввода-вывода, или проверяйте кадры `<GC>`, чтобы понять накладные расходы на сборку мусора. Опция `--native` показывает время, затраченное в расширениях C, помогая отличить накладные расходы Python от производительности библиотек.6162Для многопоточных приложений опция `-a` выполняет выборку всех потоков одновременно, показывая, как распределяется работа. А для отладки в production команда `attach` подключается к любому работающему процессу Python по PID без необходимости перезапуска или изменения кода.6364### Когда использовать детерминированную трассировку6566Детерминированный профилировщик ([`profiling.tracing`](https://python-all.ru/3.16/library/profiling.tracing.html#module-profiling.tracing)) инструментирует каждый вызов функции и возврат. Этот подход имеет более высокие накладные расходы, чем выборка, но гарантирует полное покрытие выполнения программы.6768Основная причина выбрать детерминированную трассировку – необходимость точного подсчёта вызовов. Статистическое профилирование оценивает частоту на основе выборки, что может недооценивать короткоживущие функции, которые завершаются между выборками. Если требуется проверить, что оптимизация действительно уменьшила количество вызовов функций, или проследить полный граф вызовов, чтобы понять отношения вызывающих и вызываемых функций, детерминированная трассировка – правильный выбор.6970Детерминированная трассировка также отлично подходит для захвата функций, выполняющихся за микросекунды. Такие функции могут появляться недостаточно часто в статистических выборках, но детерминированная трассировка записывает каждый вызов независимо от длительности.7172## Быстрый старт7374Этот раздел содержит минимальные шаги, необходимые для начала профилирования. Полную документацию см. на страницах, посвящённых каждому профилировщику.7576### Статистическое профилирование7778Чтобы профилировать скрипт, используйте модуль [`profiling.sampling`](https://python-all.ru/3.16/library/profiling.sampling.html#module-profiling.sampling) с командой `run`:7980```sh81python -m profiling.sampling run script.py82python -m profiling.sampling run -m mypackage.module83```8485Это запускает скрипт под профилировщиком и выводит сводку о том, где было потрачено время. Для интерактивного графа пламени:8687```sh88python -m profiling.sampling run --flamegraph script.py89```9091Чтобы профилировать уже запущенный процесс, используйте команду `attach` с идентификатором процесса:9293```sh94python -m profiling.sampling attach 123495```9697Для настраиваемых параметров укажите интервал выборки (в микросекундах) и длительность (в секундах):9899```sh100python -m profiling.sampling run -i 50 -d 30 script.py101```102103### Детерминированное профилирование104105Чтобы профилировать скрипт из командной строки:106107```sh108python -m profiling.tracing script.py109```110111Чтобы профилировать фрагмент кода программно:112113```python114import profiling.tracing115profiling.tracing.run('my_function()')116```117118Это выполняет заданный код под профилировщиком и выводит сводку, показывающую точное количество вызовов функций и время.119120## Понимание вывода профилировщика121122Оба профилировщика собирают статистику на уровне функций, хотя представляют её в разных форматах. Профилировщик на основе выборки предлагает несколько визуализаций (графы пламени, тепловые карты, Firefox Profiler, таблицы pstats), в то время как детерминированный профилировщик создаёт вывод, совместимый с pstats. Независимо от формата, основные концепции одинаковы.123124Ключевые концепции профилирования:125126****Прямое время** (также называется *собственным временем* или *tottime*)**127128Время, потраченное на выполнение кода в самой функции, за исключением времени, затраченного в вызванных ею функциях. Высокое прямое время указывает на то, что функция содержит дорогостоящие операции.129130****Совокупное время** (также называется *общим временем* или *cumtime*)**131132Время, потраченное в функции и всех вызванных ею функциях. Это измеряет общую стоимость вызова функции, включая всё поддерево вызовов.133134****Количество вызовов** (также называется *ncalls* или *выборки*)**135136Сколько раз функция была вызвана (детерминированное) или попала в выборку (статистическое). При детерминированном профилировании это точное значение. При статистическом профилировании оно представляет количество раз, когда функция появилась в стековой выборке.137138****Примитивные вызовы****139140Вызовы, которые не вызваны рекурсией. Когда функция рекурсивна, общее количество вызовов включает рекурсивные вызовы, но примитивные вызовы учитывают только первоначальный вход. Отображается как `total/primitive` (например, `3/1` означает три общих вызова, один примитивный).141142****Отношения вызывающих и вызываемых функций****143144Какие функции вызывали данную функцию (вызывающие) и какие функции она вызывала (вызываемые). Графы пламени визуализируют это в виде вложенных прямоугольников; pstats может отобразить это с помощью методов [`print_callers()`](https://python-all.ru/3.16/library/pstats.html#pstats.Stats.print_callers) и [`print_callees()`](https://python-all.ru/3.16/library/pstats.html#pstats.Stats.print_callees).145146## Совместимость с предыдущими версиями147148Для обратной совместимости модуль `cProfile` остаётся доступным как псевдоним для [`profiling.tracing`](https://python-all.ru/3.16/library/profiling.tracing.html#module-profiling.tracing). Существующий код, использующий `import cProfile`, будет продолжать работать без изменений во всех будущих версиях Python.149150Устарело с версии 3.15: Чистый Python модуль [`profile`](https://python-all.ru/3.16/library/profile.html#module-profile) устарел и будет удалён в Python 3.17. Вместо него используйте [`profiling.tracing`](https://python-all.ru/3.16/library/profiling.tracing.html#module-profiling.tracing) (или его псевдоним `cProfile`). См. `profile` для руководства по миграции.151152> **См. также**153>154> **[`profiling.sampling`](https://python-all.ru/3.16/library/profiling.sampling.html#module-profiling.sampling)**155>156> Статистический профилировщик на основе выборки с графами пламени, тепловыми картами и анализом GIL. Рекомендован для большинства пользователей.157>158> **[`profiling.tracing`](https://python-all.ru/3.16/library/profiling.tracing.html#module-profiling.tracing)**159>160> Детерминированный трассирующий профайлер для точного подсчёта вызовов.161>162> **[`pstats`](https://python-all.ru/3.16/library/pstats.html#module-pstats)**163>164> Анализ статистики и форматирование данных профилирования.165>166> **[`timeit`](https://python-all.ru/3.16/library/timeit.html#module-timeit)**167>168> Модуль для измерения времени выполнения небольших фрагментов кода.169170Подмодули171172- [`profiling.tracing` – детерминированный профилировщик](https://python-all.ru/3.16/library/profiling.tracing.html)173- [`profiling.sampling` – Статистический профилировщик](https://python-all.ru/3.16/library/profiling.sampling.html)174