Lecture preview

Профилирование Python 3.15: Tachyon вместо cProfile и итоговый проект

Как найти медленное место: timeit, cProfile, сэмплирующий профайлер Tachyon (profiling.sampling) и подключение к живому процессу. Финал: собираем трекер расходов целиком.

профилирование Tachyon flame graph оптимизация
What you will learn in this lecture
  • Находить узкие места профайлером
  • Подключаться к работающему процессу
  • Собрать законченную утилиту на Python 3.15

Beginning of the lecture

cProfile: 7 секунд превратились в 195

  • Наш отчёт по 1,5 млн трат на python:3.15-slim
  • Без профайлера: 6.95 с
  • Tachyon: 7.72 с · cProfile: 195 с
  • В статье CodeCut: +4% против ×3.4

Трекер расходов строит отчёт по полутора миллионам трат почти семь секунд. Хочется понять, что тормозит, и вы запускаете классический профайлер. Через три минуты он всё ещё работает. Мы замерили честно: без профайлера — шесть и девяносто пять сотых секунды, под классическим cProfile — сто девяносто пять секунд, почти в тридцать раз дольше. А новый профайлер Tachyon из 3.15 — семь и семь десятых. Разберёмся, почему такая разница и как искать узкие места правильно.

$ python pipeline.py                          #   6.95 с
$ python -m profiling.sampling run pipeline.py # 7.72 с
$ python -m cProfile pipeline.py              # 195 с

Правило номер один: сначала измерь

  • Кнут: «преждевременная оптимизация — корень всех зол»
  • Интуиция о медленном месте ошибается чаще, чем угадывает
  • Порядок: замер → профиль → правка → замер

Дональд Кнут когда-то сказал, что преждевременная оптимизация — корень всех зол. Смысл простой: разработчики почти всегда ошибаются, когда угадывают, где программа медленная. Вы тратите день на ускорение функции, которая занимала два процента времени, и не замечаете ту, что занимала шестьдесят. Поэтому порядок всегда один: замерили общее время, нашли профайлером горячее место, исправили именно его и замерили снова. Без второго замера вы не знаете, помогла ли правка.

timeit: точный замер маленького кусочка

  • python -m timeit — много повторов, лучший результат
  • Сравнивает варианты одной операции
  • Для целой программы — профайлер, не timeit

Начнём с самого маленького инструмента. Модуль timeit запускает кусочек кода тысячи раз и показывает, сколько занимает один запуск. Он идеален, чтобы сравнить два способа сделать одно и то же: например, найти категорию регулярным выражением или обычным поиском в словаре. Разница в нашем замере — почти в четыре раза, а на миллионах трат это уже секунды. Но timeit ничего не скажет о целой программе — для этого нужен профайлер.

$ python -m timeit -s "import re" \
    "re.search('такси', 'Такси', re.IGNORECASE)"
500000 loops, best of 5: 593 nsec per loop

$ python -m timeit -s "d = {'такси': 'Транспорт'}" \
    "d.get('Такси'.lower())"
2000000 loops, best of 5: 163 nsec per loop

The full lecture is available with a subscription

10 more slides in the full version.

The video, all slides, notes, tests, AI tutor and interview unlock after you sign in and subscribe.

Sign in or register Get a subscription

Lecture contents

  1. cProfile: 7 секунд превратились в 195
  2. Правило номер один: сначала измерь
  3. timeit: точный замер маленького кусочка
  4. Трассирующий и сэмплирующий: два способа подсматривать
  5. Что нового: Tachyon — profiling.sampling (3.15, PEP 799)
  6. Читаем профиль: кто горячий
  7. Исправляем горячее место и замеряем снова
  8. attach: профиль уже работающего процесса
  9. Режимы и форматы: flame graph, live, gil
  10. ❓ Стоп-проверка: какой режим включить?
  11. 💡 Разбор: процессор отдыхает — ищем ожидание
  12. Итоговый проект: трекер расходов целиком
  13. Что делать дальше

Articles on this lecture

All lectures in this course

  1. Python 3.15 с нуля и для опытных: что нового и как учить
  2. Python 3.15: установка, REPL и первый скрипт за десять минут
  3. Переменные, числа и строки в Python: f-строки и t-строки
  4. Условия, циклы и match/case в Python: управляем ходом программы
  5. Списки, кортежи, словари и множества: frozendict в Python 3.15
  6. Comprehensions в Python: распаковка * и ** внутри (PEP 798)
  7. Функции и аннотации типов в Python: от def до sentinel
  8. Ошибки и исключения в Python 3.15: читаем трейсбек и подсказки «Did you mean»
  9. Модули, пакеты и ленивые импорты в Python 3.15 (PEP 810)
  10. Файлы, JSON и CSV в Python: pathlib и UTF-8 по умолчанию
  11. Классы и dataclasses в Python: ООП без лишнего кода
  12. Асинхронность и потоки в Python: asyncio, TaskGroup и free-threading
  13. Профилирование Python 3.15: Tachyon вместо cProfile и итоговый проект