0Pricing
Python Academy · Урок

Профилирование с 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 functions

line_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.py

CLI 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 loop

py-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 — локальная установка не требуется.

Все уроки этого курса

  1. Подсчёт ссылок в CPython
  2. Сборщик мусора и циклические ссылки
  3. Профилирование с cProfile и line_profiler
  4. Профилирование памяти с tracemalloc
← Назад к Python Academy