Профилирование Python: cProfile, py-spy, line_profiler
Три инструмента на три задачи: где время, где строки, где в проде (без перекомпиляции).
cProfile — встроенный, статистический
Собирает время на каждую функцию. Точность ~10% overhead. Хорошо для «что горячее».
# CLI
python -m cProfile -s cumulative main.py
# В коде
import cProfile, pstats
prof = cProfile.Profile()
prof.enable()
# ... код ...
prof.disable()
stats = pstats.Stats(prof).sort_stats('cumulative')
stats.print_stats(20)
Ограничение: не показывает строки внутри функции, только саму функцию.
py-spy — sampling, работает в проде
Сэмплирует стек каждые N миллисекунд. Overhead <1%. Можно прицепиться к уже запущенному процессу.
# Фламм-чарт (SVG)
py-spy record -o flame.svg -- python app.py
# Топ функций (live)
py-spy top --pid 12345
# Статический снимок
py-spy dump --pid 12345
Не требует root (если Yama ptrace_scope позволяет). Идеален для Docker-контейнеров: py-spy top --pid 1.
line_profiler — построчно
Показывает, какая именно строка внутри функции ест время. Overhead высокий (~2-5x), только для dev.
# Установить
pip install line_profiler
# В коде
@profile
def process(data):
result = []
for item in data:
result.append(transform(item)) # ← эта строка горячая?
return result
# Запуск
kernprof -l -v main.py
Когда что
| Задача | Инструмент |
|---|---|
| Где время (быстрый ответ) | cProfile |
| Прод, без остановки | py-spy |
| Какая строка внутри функции | line_profiler |
| Алокации памяти | memory_profiler / tracemalloc |
Совет
Начинай с py-spy top — 30 секунд, ноль изменений в коде. Если увидел горячую функцию — тогда line_profiler внутри неё.