Короткий ответ
Для production используют сэмплирующие профилировщики, которые подключаются к уже запущенному процессу извне и периодически снимают стек вызовов (например, py-spy), а не инструментирующие профилировщики вроде cProfile, которые перехватывают каждый вызов функции и создают существенный overhead.
Как это работает подробнее
Сэмплирующий профилировщик с заданной частотой (например, 100 Гц) читает текущий стек вызовов процесса, не изменяя байткод и не добавляя накладных расходов на каждый вызов; статистически по множеству сэмплов восстанавливается, где процесс проводит больше всего времени.
Пример кода
commands.sh
py-spy record -o profile.svg --pid 12345 --duration 30
# результат — флейм-график (SVG), где ширина блока функции
# пропорциональна доле времени, которое процесс провёл в ней за 30 секундЧто использовать на практике
- Практика. py-spy можно запускать с флагом --pid на уже работающем процессе без его остановки и без изменений в коде; для веб-приложений полезно снимать профиль именно во время пиковой нагрузки, а не в синтетическом тесте, чтобы увидеть реальные узкие места, включая время в сторонних библиотеках.
Подводные камни
- Риск. Включают cProfile в production без ограничения по времени и трафику, что заметно замедляет обработку запросов; делают выводы по одному короткому снятому профилю, не учитывая, что нагрузка и узкие места могут отличаться в разное время суток.