Senior‑ответ важен не перечнем инструментов, а пониманием, когда к какому подходу тянуться.
CPU-профилирование: cProfile + pstats
cProfile — встроенный детерминированный профилировщик CPU:
инструментирует каждый вызов функции, считает общее и собственное время;
даёт подробный call graph, но вносит заметный overhead;
отлично подходит для локального анализа, бенчей и одноразовых исследований.
import cProfile, pstats
pr = cProfile.Profile()
pr.enable()
# ... код для профилирования ...
pr.disable()
stats = pstats.Stats(pr)
stats.sort_stats("cumulative").print_stats(20)
Часто вывод импортируют в инструменты визуализации (snakeviz, gprof2dot + Graphviz) для удобного анализа.
Сэмплирующие профайлеры: py-spy и аналоги
py-spy — внешний сэмплирующий профилировщик:
подключается к уже запущенному процессу, не требует изменения кода;
регулярно «снимает стек» (sampling), строит flamegraph и статистику по функциям;
имеет куда меньший overhead и подходит для продакшена (осторожно, но реально применимо);
умеет работать с многопоточными/async‑приложениями.
Плюс сэмплирующих профайлеров в том, что они не искажают нагрузку столь сильно, как детерминированные, и позволяют подобрать «горячие» участки на бою.
Память: memory_profiler, tracemalloc, objgraph
memory_profiler — измеряет использование памяти по строкам/функциям; часто используется через декоратор @profile или командную утилиту; позволяет увидеть, какие участки кода дают рост RSS процесса.
tracemalloc (стандартная библиотека) отслеживает выделения памяти в Python‑объектах, даёт срезы по top‑allocations, умеет сравнивать снимки до/после, помогает в поиске утечек и неожиданных аллокаций.
objgraph и подобные библиотеки полезны для анализа графа объектов: какие типы растут, какие объекты держат ссылки на другие.
Практический workflow
Типичный подход senior‑разработчика:
сначала — высокоуровневые метрики (APM, метрики latency/CPU/RSS), чтобы понять, есть ли вообще проблема;
для CPU — локально cProfile на репрезентативном нагрузочном сценарии, а если нужно — py-spy или аналог на staging/production для уточнения «горячих» функций;
для памяти — tracemalloc/memory_profiler на подозрительных путях, сравнение снимков, поиск мест, где количество объектов растёт и не падает.
Формулировка для собеседования
Для профилирования CPU я обычно начинаю с cProfile + pstats локально, а при необходимости использую сэмплирующий профайлер вроде py-spy, который можно подключить даже к живому процессу и посмотреть flamegraph с меньшим overhead’ом. Для памяти — memory_profiler и tracemalloc, иногда с objgraph, чтобы увидеть, какие объекты растут. Дальше уже принимаю архитектурные решения: менять алгоритм, структуру данных, точки кеширования и т.п.