Профилируем Python в продакшене: почему cProfile не подходит, и чем хорош py-spy Когда на проде начинает течь память или скачет CPU, первая мысль, под…
Когда на проде начинает течь память или скачет CPU, первая мысль, подключить профайлер. Стандартный cProfile, это детерминированный профайлер. Он хукает каждый вызов функции.
📉 Цена: Оверхед может замедлить приложение в 2-5 раз. На нагруженном проде это означает добить сервис окончательно.
Для Live-систем нужен Sampling Profiler (сэмплирующий профайлер). Золотой стандарт сейчас - py-spy.
Как это работает?
py-spy написан на Rust. Он работает как внешний процесс, который читает память вашего Python-процесса (через системные вызовы, аналогично gdb). Он делает «снимки» стека вызовов с высокой частотой (по дефолту 100 раз в секунду).
✅ Результат: Оверхед стремится к нулю. Код инструментализировать не нужно. Рестарт сервиса не нужен.
Два главных режима работы:
1. Live View (как htop, но для функций)
Посмотреть в реальном времени, в каких функциях процесс проводит больше всего времени.
# Нужно только знать PID процесса
py-spy top --pid 12345
Вы увидите список функций, отсортированный по OwnTime (время внутри функции) и TotalTime (время с учетом дочерних вызовов).
2. Flame Graph (Огненный граф)
Для глубокого анализа лучше записать работу сервиса за период и визуализировать стек.
py-spy record -o profile.svg --pid 12345 --duration 60
Вы получите SVG-файл. Чем шире полоска, тем больше времени занимает функция. Вертикаль - это глубина стека. Сразу видно, кто «съел» процессорное время.
Нюансы для Middle+:
- GIL: py-spy умеет показывать, держит ли функция GIL. Добавьте флаг --gil.
- Docker/K8s: Так как py-spy использует системный вызов ptrace, контейнеру нужны привилегии. В Kubernetes часто нужно добавить securityContext: capabilities: add: ["SYS_PTRACE"] подам, чтобы иметь возможность профилировать их на лету.
#profiling #optimization #pyspy #debugging #python
👉 @BookPython