Code-Profilierung ist der systematische Prozess der Performance-Analyse eines Programms, um Engpässe zu identifizieren und die Anwendung zu optimieren. In Python gibt es zahlreiche Werkzeuge zur Messung von Ausführungszeit, Speicherverbrauch und anderen kritischen Metriken.
Grundlagen der Python-Code-Profilierung
Profilierung ist eine dynamische Analyse des Programms, die Folgendes misst:
- Ausführungszeit einzelner Funktionen
- Anzahl der Methodenaufrufe
- Arbeitsspeicherverbrauch
- CPU-Auslastung
Das Hauptziel der Profilierung ist es, kritische Codeabschnitte zu identifizieren, die die Anwendung verlangsamen und optimiert werden müssen.
Wann sollte man profilieren?
Profilierung ist besonders in folgenden Fällen sinnvoll:
Anwendungsperformance: Wenn das Programm langsamer läuft als erwartet, hilft die Profilierung, die Ursachen der Verlangsamung zu finden.
Hoher Ressourcenverbrauch: Bei übermäßiger CPU- oder RAM-Nutzung zeigt die Profilierung, welche Funktionen die meisten Ressourcen verbrauchen.
Vorbereitung für den Produktionseinsatz: Vor dem Deployment kritischer Anwendungen stellt die Profilierung sicher, dass sie effizient arbeiten.
Algorithmen-Optimierung: Bei großen Datenmengen oder komplexen Berechnungen deckt die Profilierung ineffiziente Algorithmen auf.
Integrierte Profiling-Tools
Das cProfile-Modul
cProfile ist der Standard-Profiler von Python und Teil des Interpreters. Er eignet sich für die allgemeine Performance-Analyse von Programmen.
import cProfile
def fibonacci(n):
if n <= 1:
return n
return fibonacci(n-1) + fibonacci(n-2)
def test_function():
result = fibonacci(30)
return result
# Profiling starten
cProfile.run('test_function()')
Das Profiling-Ergebnis enthält wichtige Metriken:
ncalls— Gesamtzahl der Funktionsaufrufetottime— Ausführungszeit der Funktion ohne verschachtelte Aufrufepercall— Durchschnittliche Zeit pro Aufrufcumtime— Gesamtzeit inklusive aller verschachtelten Aufrufefilename:lineno(function)— Position der Funktion im Code
Das timeit-Modul für punktuelle Messungen
Zur Messung der Ausführungszeit kleiner Codeabschnitte wird das timeit-Modul verwendet:
import timeit
# Vergleich verschiedener Methoden zur Listenerstellung
list_comprehension = timeit.timeit('[i*2 for i in range(1000)]', number=1000)
map_function = timeit.timeit('list(map(lambda x: x*2, range(1000)))', number=1000)
print(f"List comprehension: {list_comprehension:.6f} Sekunden")
print(f"Map function: {map_function:.6f} Sekunden")
Das profile-Modul für detaillierte Analysen
Ein alternativer integrierter Profiler, der langsamer als cProfile ist, aber detailliertere Informationen liefert:
import profile
def complex_calculation():
data = []
for i in range(10000):
data.append(i ** 2)
return sum(data)
profile.run('complex_calculation()')
Externe Profiling-Tools
line_profiler — zeilenweise Profilierung
Dieses Tool zeigt die Ausführungszeit jeder einzelnen Codezeile an:
pip install line_profiler
@profile
def process_data():
data = []
for i in range(100000): # Diese Zeile könnte ein Engpass sein
data.append(i * 2)
return sum(data)
Starten der zeilenweisen Profilierung:
kernprof -l -v script.py