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

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

@potapov_me

Платформа

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

Контент

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

Компания

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

Аккаунт

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

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

·ИП Потапов К.С.·Политика конфиденциальности·
Сделано с ❤️ в России
  1. Запись и Flame Graphs
record

Запись и Flame Graphs

Команда record, запись в SVG, анализ flame graph, поиск узких мест

Запись и анализ Flame Graphs

Одна картинка стоит тысячи слов. Один SVG стоит тысячи догадок.

Команда record — основной инструмент py-spy для записи профиля. Она запускает программу (или подключается к существующей) и записывает данные в файл для последующего анализа.

#Базовый синтаксис

py-spy record [ОПЦИИ] -- [КОМАНДА PYTHON] py-spy record [ОПЦИИ] --pid <PID>

Важно: Флаг -- отделяет аргументы py-spy от аргументов команды Python.

#Форматы вывода

py-spy поддерживает несколько форматов:

ФорматФлагОписание
flamegraph (SVG)--format flamegraphИнтерактивный SVG для браузера
icicle (SVG)--format icicleПеревёрнутый flamegraph (по умолчанию)
raw--format rawСырые данные для парсинга
speedscope--format speedscopeДля speedscope.app

#SVG (flamegraph / icicle)

Рекомендуется для большинства случаев. Открывается в любом браузере, интерактивный, можно отправить коллеге.

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

Разница между flamegraph и icicle:

  • flamegraph: Корень (main) сверху, вызываемые функции ниже
  • icicle: Корень (main) снизу, вызываемые функции выше

icicle более интуитивен — «растёт» вверх как вызовы функций.

#Speedscope

Формат для speedscope.app — продвинутого веб-инструмента для анализа профилей.

py-spy record -o profile.speedscope --format speedscope -- python my_script.py

Преимущества speedscope:

  • Поддерживает несколько потоков
  • Показывает временную шкалу (left-heavy view)
  • Умеет искать по функциям
  • Показывает reverse stack trace (что вызывало эту функцию)

#Raw формат

Сырые данные для программной обработки:

py-spy record -o profile.raw --format raw -- python my_script.py

Формат: каждая строка содержит стек вызовов и количество сэмплов.

#Длительность записи

По умолчанию py-spy записывает 30 секунд или до завершения процесса.

#Фиксированная длительность

# Записать 60 секунд py-spy record -o profile.svg --duration 60 --pid 12345

#До завершения процесса

# Запись остановится, когда скрипт завершится py-spy record -o profile.svg -- python long_running_script.py

#Бесконечная запись (до Ctrl+C)

# Записывает, пока не нажмёте Ctrl+C py-spy record -o profile.svg --duration 0 --pid 12345

#Частота семплирования

По умолчанию py-spy делает 100 снимков в секунду.

#Увеличение точности

# 200 снимков в секунду — более точные данные py-spy record -o profile.svg --rate 200 --pid 12345

#Снижение оверхеда для продакшена

# 20 снимков в секунду — минимальный оверхед py-spy record -o profile.svg --rate 20 --pid 12345

Компромисс:

  • Высокий rate (200+) → точнее, но больше оверхед
  • Низкий rate (10-20) → меньше оверхед, но можно пропустить короткие функции

#Анализ SVG в браузере

Откройте profile.svg в браузере. Вы увидите:

┌─────────────────────────────────────────────────────┐
│                process_data (45%)                   │ ← Самая широкая
├─────────────────────────────────────────────────────┤
│         parse_json (30%)      save_to_db (15%)      │
├─────────────────────┬─────────┴──────────┬──────────┤
│   extract_fields    │  validate_schema   │  query   │
│      (18%)          │      (12%)         │  (10%)   │
└─────────────────────┴────────────────────┴──────────┘

#Как читать

  1. Ширина = время: Чем шире полоса, тем больше времени программа провела в этой функции.

  2. Вертикаль = иерархия: Функции выше вызывают функции ниже.

  3. Ищите широкие полосы: Это кандидаты на оптимизацию.

  4. Обращайте внимание на «плечи»: Если функция широкая, но её дети узкие — время тратится внутри самой функции (циклы, вычисления).

#Интерактивность

SVG от py-spy интерактивный:

  • Наведение: Подсвечивает функцию, показывает точный процент
  • Клик: Zoom в функцию (показывает только её детей)
  • Двойной клик: Zoom out

#Практический пример: Поиск узкого места

#Скрипт для профилирования

Создайте api_simulator.py:

import time import json import hashlib def fetch_data(): """Симуляция запроса к БД""" time.sleep(0.1) return {"users": list(range(1000))} def validate_schema(data): """Валидация данных""" time.sleep(0.05) return True def extract_fields(data): """Извлечение полей — намеренно медленное""" result = [] for item in data["users"]: # Неоптимально: создаём строку на каждой итерации key = f"user_{item}" hashed = hashlib.md5(key.encode()).hexdigest() result.append({"id": item, "hash": hashed}) return result def save_to_db(records): """Симуляция сохранения""" time.sleep(0.08) return len(records) def process_request(): """Обработка одного запроса""" data = fetch_data() if not validate_schema(data): return None records = extract_fields(data) save_to_db(records) return records def main(): """Симуляция 10 запросов""" for i in range(10): process_request() print("Готово!") if __name__ == "__main__": main()

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

py-spy record -o api_profile.svg -- python api_simulator.py

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

Откройте api_profile.svg. Вы увидите:

  1. process_request занимает ~90% времени (ожидаемо — это основная функция)
  2. Внутри extract_fields занимает ~50% — это узкое место!
  3. fetch_data и save_to_db по ~15% — меньше, чем вычисления

Вывод: Оптимизируйте extract_fields. Например, уберите создание строки f"user_{item}" внутри цикла.

#Оптимизированная версия

def extract_fields_optimized(data): """Оптимизированная версия""" result = [] for item in data["users"]: # Оптимизация: хэшируем число напрямую key = str(item) hashed = hashlib.md5(key.encode()).hexdigest() result.append({"id": item, "hash": hashed}) return result

Запрофилируйте ещё раз — extract_fields должна стать уже.

#Профилирование с аргументами

Если скрипт принимает аргументы:

py-spy record -o profile.svg -- python my_script.py --arg1 value1 --arg2 value2

#Профилирование модуля

py-spy record -o profile.svg -- python -m my_module

#Профилирование с переменными окружения

py-spy record -o profile.svg -- env FLASK_ENV=production python app.py

#Частые проблемы

#«Error: Permission denied»

На Linux/macOS может потребоваться sudo:

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

#«Error: No such process»

Процесс завершился до запуска py-spy. Используйте -- для запуска с начала:

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

#Пустой SVG

Программа завершилась слишком быстро. Увеличьте длительность или количество данных:

py-spy record -o profile.svg --duration 60 --pid 12345

Далее: Интерактивный мониторинг