Профилирование с cProfile и line_profiler
Находите узкие места по нагрузке на CPU с помощью cProfile и построчного профилирования.
«Профилирование с cProfile и line_profiler» — бесплатный урок Python Academy на CoddyKit. Это урок 3 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Python Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Python Academy содержит 4 уроков всего.
Зачем профилировать
Профилирование показывает, какие функции занимают больше всего времени, и помогает направить работу по оптимизации. Всегда профилируйте код перед оптимизацией — не пытайтесь угадать.
import cProfile
def slow():
total = 0
for i in range(1_000_000):
total += i
return total
cProfile.run("slow()")Запуск cProfile из CLI
Профилируйте весь скрипт без его изменения: python -m cProfile -s cumtime script.py. Сортируйте по cumtime, tottime или calls.
# python -m cProfile -s cumtime my_script.py
#
# ncalls tottime percall cumtime percall filename:lineno(function)
# 1000 0.500 0.001 2.100 0.002 utils.py:10(process)cProfile в коде
Создайте объект cProfile.Profile, включите и отключите его, затем выведите статистику с помощью pstats.
import cProfile, pstats, io
pr = cProfile.Profile()
pr.enable()
# ... code to profile ...
pr.disable()
stream = io.StringIO()
ps = pstats.Stats(pr, stream=stream).sort_stats("cumulative")
ps.print_stats(10) # top 10
print(stream.getvalue())Фильтрация в pstats
Отфильтруйте вывод профилировщика по определённому модулю или шаблону имени функции с помощью print_stats(pattern).
import cProfile, pstats
cProfile.run("my_function()", "profile.out")
stats = pstats.Stats("profile.out")
stats.sort_stats("tottime")
stats.print_stats("mymodule") # only mymodule functionsline_profiler
line_profiler показывает время выполнения для каждой строки, а не только для каждой функции, — это необходимо для поиска самой медленной строки внутри функции.
# pip install line_profiler
# Decorate target function:
from line_profiler import profile
@profile
def process(data):
result = []
for item in data: # <- which line is slow?
result.append(item*2)
return result
# Run: kernprof -l -v script.pyCLI kernprof
kernprof -l script.py запускает скрипт с включённым построчным профилированием; параметр -v сразу отображает отчёт.
# kernprof -l -v script.py
#
# Line # Hits Time Per Hit % Time Line Contents
# ======================================================
# 4 1 2.0 2.0 1.0 result = []
# 5 1000 120.0 0.1 60.0 for item in data:
# 6 1000 80.0 0.1 39.0 result.append(item*2)Профилирование в Jupyter
Jupyter предоставляет магические команды %prun (cProfile) и %lprun (line_profiler).
# In a Jupyter cell:
# %prun -s cumulative my_function(data)
# %load_ext line_profiler
# %lprun -f my_function my_function(data)Поиск узких мест
Сосредоточьтесь на функциях с наибольшим суммарным временем (вся цепочка вызовов) и наибольшим общим временем (сама функция без вызываемых ею функций).
# cumtime = total time including callees (find root cause)
# tottime = time in function itself (find where work happens)
#
# Optimise the function with highest tottime firstКак избежать преждевременной оптимизации
Сначала выполните профилирование, затем оптимизируйте измеренное узкое место. Распространённые способы ускорить Python: используйте встроенные средства, переносите циклы в NumPy, кэшируйте повторяющиеся обращения или вызывайте C через ctypes/cffi.
# Before optimising:
# profile shows: process_row() 95% of time
# Speedup: vectorise with NumPy
import numpy as np
arr = np.array(data)
result = arr * 2 # 100x faster than Python looppy-spy: профилировщик на основе выборки
py-spy профилирует работающие процессы без изменения кода — подключитесь к активному PID.
# pip install py-spy
# Profile for 30 s and show flamegraph:
# py-spy top --pid 12345
# py-spy record -o profile.svg --pid 12345 --duration 30Сравнительное тестирование с timeit
Используйте timeit для микроизмерений времени выполнения отдельных выражений.
import timeit
result = timeit.timeit(
"[x*2 for x in range(1000)]",
number=10_000
)
print(f"{result:.3f} s for 10k runs")Быстрая проверка
Что показывает tottime в отчёте cProfile?
Итоги
Используйте cProfile, чтобы находить медленные функции, а line_profiler — чтобы находить медленные строки. Выполняйте профилирование с параметром -s cumtime, чтобы находить первопричины. Оптимизируйте только подтверждённые узкие места — для наибольшего эффекта используйте векторизацию NumPy, кэширование или расширения на C.
Часто задаваемые вопросы
Урок «Профилирование с cProfile и line_profiler» бесплатный?
Да — полный текст урока «Профилирование с cProfile и line_profiler» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Python Academy, подпишись на CoddyKit PRO. Курс Python Academy содержит 4 уроков всего.
Чему я научусь в уроке «Профилирование с cProfile и line_profiler»?
Находите узкие места по нагрузке на CPU с помощью cProfile и построчного профилирования. Ты практикуешь Python Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Python Academy?
Предыдущий опыт не требуется. Python Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 3 из 4.
Сколько времени занимает урок «Профилирование с cProfile и line_profiler»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Python Academy?
Да. Каждый урок Python Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Подсчёт ссылок в CPython
- Сборщик мусора и циклические ссылки
- Профилирование с cProfile и line_profiler
- Профилирование памяти с tracemalloc