Перейти к основному контенту
Tech Path Finder
КурсыИнтервьюКод-ревьюБлог
Tech Path Finder

Персонализированный путеводитель в IT. Квизы, мок-интервью, код ревью и аналитика прогресса.

@potapov_me

Платформа

  • Курсы
  • Прогресс
  • Мок-интервью
  • Код ревью
  • Живое ревью с ИИ
  • Тренажёр переговоров
  • Закладки

Контент

  • Блог
  • Главная
  • Обратная связь

Компания

  • О проекте
  • Тарифы
  • Условия использования
  • Конфиденциальность
  • Согласие на обработку данных
  • Cookie
  • Реквизиты

Аккаунт

  • Войти
  • Зарегистрироваться
  • Профиль

© 2026 Tech Path Finder. Все права защищены.

·ИП Потапов К.С.·Политика конфиденциальности·
Сделано с ❤️ в России
  1. Введение и установка
intro

Введение и установка

Что такое py-spy, отличие от cProfile, установка и первое профилирование

Введение и установка

Профилирование — это не оптимизация. Это понимание того, что на самом деле делает ваш код.

#Почему py-spy?

Представьте: у вас есть медленный API, который отвечает 5 секунд вместо 200 мс. Где проблема?

Без профилирования вы будете:

  • Смотреть на код и гадать: «Может, этот цикл слишком медленный?»
  • Добавлять print(time.time()) в разные места
  • Менять случайные вещи в надежде, что поможет

С профилированием вы:

  • Запускаете одну команду
  • Видите точную функцию, которая занимает 80% времени
  • Оптимизируете то, что действительно важно

#Чем py-spy отличается от cProfile?

ХарактеристикаcProfilepy-spy
ТипДетерминированныйСемплирующий
Замедление2-10×<5%
Работа с продакшеном❌ Нельзя✅ Можно
Модификация кодаТребуется импортНе требуется
Нативные расширенияНе показываетПоказывает (с --native)
MultiprocessingСложноРаботает из коробки

Детерминированный профилировщик (cProfile) отслеживает каждый вызов функции. Это даёт точные данные, но замедляет программу.

Семплирующий профилировщик (py-spy) периодически снимает «снимки» стека вызовов. Например, 100 раз в секунду. Если функция появилась в 50 снимках из 100, она занимала ~50% времени.

Почему это важно? py-spy можно запустить на работающем продакшен-сервере без остановки и без заметного влияния на пользователей.

#Установка

py-spy — это один бинарный файл. Никаких зависимостей, никаких pip install.

#macOS

brew install py-spy

Или скачайте с GitHub Releases:

curl -L https://github.com/benfred/py-spy/releases/download/v0.4.0/py-spy-0.4.0-x86_64-apple-darwin.tar.gz | tar xz mv py-spy /usr/local/bin/

#Linux

pip install py-spy

Или скачайте бинарник:

curl -L https://github.com/benfred/py-spy/releases/download/v0.4.0/py-spy-0.4.0-x86_64-unknown-linux-gnu.tar.gz | tar xz sudo mv py-spy /usr/local/bin/

#Windows

Скачайте .exe с GitHub Releases и поместите в PATH.

#Проверка установки

py-spy --version # py-spy 0.4.0

#Первое профилирование

Создайте тестовый скрипт slow_script.py:

import time import math def slow_function(): """Намеренно медленная функция""" total = 0 for i in range(1_000_000): total += math.sqrt(i) return total def fast_function(): """Быстрая функция""" return sum(range(100)) def main(): print("Начало работы...") # Медленная часть for _ in range(5): slow_function() # Быстрая часть for _ in range(100): fast_function() print("Готово!") if __name__ == "__main__": main()

#Запуск с профилированием

Способ 1: Профилирование с запуска

py-spy record -o profile.svg -- python slow_script.py

Что происходит:

  1. py-spy запускает python slow_script.py
  2. Делает 100 снимков стека в секунду
  3. После завершения скрипта создаёт profile.svg

Способ 2: Профилирование работающего процесса

Запустите скрипт в одном терминале:

python slow_script.py

Найдите PID (в другом терминале):

ps aux | grep slow_script # или pgrep -f slow_script.py

Запустите профилирование:

py-spy record -o profile.svg --pid <PID>

Важно: На macOS и Linux может потребоваться sudo для профилирования работающего процесса:

sudo py-spy record -o profile.svg --pid 12345

#Анализ результата

Откройте profile.svg в браузере. Вы увидите icicle graph (граф-сосульку):

┌─────────────────────────────────────────┐
│           slow_function (85%)           │ ← Занимает 85% времени
├─────────────────────────────────────────┤
│     main (90%)      fast_function (5%)  │
└─────────────────────────────────────────┘

Как читать:

  • Ширина полосы = процент времени, проведённого в функции
  • Вертикальная позиция = иерархия вызовов (кто кого вызвал)
  • Узкие места = широкие полосы, которые вы хотите оптимизировать

В нашем примере вы сразу увидите, что slow_function занимает почти всё время.

#Почему это работает без остановки кода?

py-spy использует возможности операционной системы для чтения памяти другого процесса:

  • Linux: /proc/<PID>/mem и /proc/<PID>/regs
  • macOS: task_for_pid и Mach API
  • Windows: ReadProcessMemory

Он читает структуры данных интерпретатора Python (фреймы, кодовые объекты) напрямую из памяти. Программа продолжает выполняться — py-spy просто «подглядывает».

Безопасно ли это? Да. py-spy только читает память, не модифицирует её. Это как сделать фотографию — программа не знает, что её профилируют.

#Ограничения py-spy

  1. Точность: Семплирование даёт статистическую картину, а не точные числа. Для 99% случаев этого достаточно.

  2. Короткие функции: Если функция выполняется быстрее интервала семплирования (10 мс по умолчанию), она может не попасть в профиль.

  3. Требования к процессу:

    • Python должен быть собран с фрейм-информацией (стандартные сборки подходят)
    • На Linux может потребоваться ptrace_scope=0 (см. ниже)

#Решение проблем на Linux

Если py-spy не подключается к процессу:

# Проверьте ptrace_scope cat /proc/sys/kernel/yama/ptrace_scope # Если не 0, временно отключите echo 0 | sudo tee /proc/sys/kernel/yama/ptrace_scope

Или используйте --non-blocking флаг.

#Практическое задание

  1. Установите py-spy
  2. Создайте slow_script.py из примера выше
  3. Запустите профилирование: py-spy record -o profile.svg -- python slow_script.py
  4. Откройте profile.svg в браузере
  5. Найдите функцию, которая занимает больше всего времени

Ключевая идея: py-spy даёт вам данные, а не догадки. Одна команда — и вы видите, где программа на самом деле проводит время.

Далее: Запись и Flame Graphs