0Pricing
Python Academy · Lekcja

Profilowanie za pomocą cProfile i line_profiler

Proszę znajdować wąskie gardła procesora za pomocą cProfile i profilowania linia po linii.

Profilowanie za pomocą cProfile i line_profiler to bezpłatna lekcja Python Academy na CoddyKit. To lekcja 3 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Python Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Python Academy zawiera 4 lekcji w sumie.

Po co profilować?

Profilowanie pozwala określić, które funkcje zużywają najwięcej czasu, i ukierunkować działania optymalizacyjne. Zawsze należy profilować przed optymalizacją — nie należy zgadywać.

import cProfile

def slow():
    total = 0
    for i in range(1_000_000):
        total += i
    return total

cProfile.run("slow()")

Uruchamianie cProfile z wiersza poleceń

Proszę profilować cały skrypt bez jego modyfikowania: python -m cProfile -s cumtime script.py. Wyniki można sortować według cumtime, tottime lub 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 w kodzie

Należy utworzyć obiekt cProfile.Profile, włączać i wyłączać profilowanie, a następnie wyświetlać statystyki za pomocą 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())

Filtrowanie za pomocą pstats

Wyjście profilera można ograniczyć do określonego modułu lub wzorca nazwy funkcji za pomocą 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 pokazuje czas wykonania poszczególnych wierszy, a nie tylko funkcji — jest niezbędny do znalezienia najbardziej obciążającego wiersza wewnątrz funkcji.

# 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

Interfejs wiersza poleceń kernprof

kernprof -l script.py uruchamia skrypt z włączonym profilowaniem wierszy; opcja -v natychmiast wyświetla raport.

# 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)

Profilowanie w Jupyterze

Jupyter udostępnia magiczne polecenia %prun (cProfile) i %lprun (line_profiler).

# In a Jupyter cell:
# %prun -s cumulative my_function(data)

# %load_ext line_profiler
# %lprun -f my_function my_function(data)

Identyfikowanie hotspotów

Należy skupić się na funkcjach o największym skumulowanym czasie (obejmującym cały łańcuch wywołań) oraz o największym całkowitym czasie (dotyczącym samej funkcji, bez wywoływanych przez nią funkcji).

# cumtime = total time including callees (find root cause)
# tottime = time in function itself (find where work happens)
#
# Optimise the function with highest tottime first

Unikanie przedwczesnej optymalizacji

Najpierw należy wykonać profilowanie, a następnie zoptymalizować zmierzone wąskie gardło. Typowe sposoby przyspieszania kodu w Pythonie to używanie funkcji wbudowanych, przenoszenie pętli do NumPy, buforowanie powtarzających się wyszukiwań lub wywoływanie kodu C za pomocą 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: profiler próbkowany

py-spy profiluje uruchomione procesy bez modyfikowania kodu — można dołączyć go do aktywnego identyfikatora 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

Testy wydajności za pomocą timeit

Należy używać timeit do mikrotestów wydajności określonych wyrażeń.

import timeit

result = timeit.timeit(
    "[x*2 for x in range(1000)]",
    number=10_000
)
print(f"{result:.3f} s for 10k runs")

Szybkie sprawdzenie

Co pokazuje tottime w raporcie cProfile?

Podsumowanie

Należy używać cProfile do znajdowania wolnych funkcji, a line_profiler do znajdowania wolnych wierszy. Profilowanie z opcją -s cumtime pomaga znaleźć przyczyny źródłowe. Optymalizować należy wyłącznie potwierdzone hotspoty — największe korzyści zapewniają wektoryzacja za pomocą NumPy, buforowanie lub rozszerzenia w języku C.

Często zadawane pytania

Czy lekcja „Profilowanie za pomocą cProfile i line_profiler” jest bezpłatna?

Tak — pełny tekst „Profilowanie za pomocą cProfile i line_profiler” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Python Academy, przejdź na CoddyKit PRO. Kurs Python Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Profilowanie za pomocą cProfile i line_profiler”?

Proszę znajdować wąskie gardła procesora za pomocą cProfile i profilowania linia po linii. Ćwiczysz Python Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć Python Academy?

Nie wymagamy żadnego doświadczenia. Python Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 3 z 4.

Ile czasu zajmuje lekcja „Profilowanie za pomocą cProfile i line_profiler”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji Python Academy?

Tak. Każda lekcja Python Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Zliczanie odwołań w CPythonie
  2. Garbage collector i cykliczne odwołania
  3. Profilowanie za pomocą cProfile i line_profiler
  4. Profilowanie pamięci za pomocą tracemalloc
← Powrót do Python Academy