Project Euler und andere Codierungswettbewerbe haben häufig eine maximale Laufzeit oder die Benutzer geben an, wie schnell ihre jeweilige Lösung ausgeführt wird. Bei Python sind die Ansätze manchmal etwas kludgey - dh das Hinzufügen von Timing-Code zu __main__
.
Wie lässt sich feststellen, wie lange die Ausführung eines Python-Programms dauert?
python
performance
profiling
time-complexity
Chris Lawlor
quelle
quelle
Antworten:
Python enthält einen Profiler namens cProfile . Es gibt nicht nur die Gesamtlaufzeit an, sondern auch die Zeiten für jede Funktion separat und gibt an, wie oft jede Funktion aufgerufen wurde, sodass Sie leicht bestimmen können, wo Sie Optimierungen vornehmen sollten.
Sie können es aus Ihrem Code oder vom Interpreter wie folgt aufrufen:
Noch nützlicher ist, dass Sie das cProfile aufrufen können, wenn Sie ein Skript ausführen:
Um es noch einfacher zu machen, habe ich eine kleine Batch-Datei namens 'profile.bat' erstellt:
Alles was ich tun muss ist laufen:
Und ich verstehe das:
BEARBEITEN: Der Link zu einer guten Video-Ressource von PyCon 2013 mit dem Titel Python- Profilerstellung wurde
ebenfalls über YouTube aktualisiert .
quelle
python -m cProfile -o <out.profile> <script>
) wird RunSnakeRun aufgerufen, da dies vonrunsnake <out.profile>
unschätzbarem Wert ist.cprofile
empfohlen, immer noch überprofile
.Vor einiger Zeit habe ich gemacht
pycallgraph
, die eine Visualisierung aus Ihrem Python-Code generiert. Bearbeiten: Ich habe das Beispiel aktualisiert, um mit 3.3 zu arbeiten, der neuesten Version zum Zeitpunkt dieses Schreibens.Nach dem
pip install pycallgraph
Installieren von GraphViz können Sie es über die Befehlszeile ausführen:Oder Sie können bestimmte Teile Ihres Codes profilieren:
Beides generiert eine
pycallgraph.png
Datei ähnlich dem folgenden Bild:quelle
Traceback (most recent call last): /pycallgraph.py", line 90, in generate output.done() File "/net_downloaded/pycallgraph-develop/pycallgraph/output/graphviz.py", line 94, in done source = self.generate() File "/net_downloaded/pycallgraph-develop/pycallgraph/output/graphviz.py", line 143, in generate indent_join.join(self.generate_attributes()), File "/net_downloaded/pycallgraph-develop/pycallgraph/output/graphviz.py", line 169, in generate_attributes section, self.attrs_from_dict(attrs), ValueError: zero length field name in format
sudo apt-get install graphviz
.Es ist erwähnenswert, dass die Verwendung des Profilers (standardmäßig) nur für den Hauptthread funktioniert und Sie keine Informationen von anderen Threads erhalten, wenn Sie diese verwenden. Dies kann ein kleines Problem sein, da es in der Profiler-Dokumentation völlig unerwähnt ist .
Wenn Sie auch Threads profilieren möchten, sollten Sie sich die
threading.setprofile()
Funktion in den Dokumenten ansehen .Sie können dazu auch eine eigene
threading.Thread
Unterklasse erstellen :und verwenden Sie diese
ProfiledThread
Klasse anstelle der Standardklasse. Es gibt Ihnen vielleicht mehr Flexibilität, aber ich bin mir nicht sicher, ob es sich lohnt, insbesondere wenn Sie Code von Drittanbietern verwenden, der Ihre Klasse nicht verwenden würde.quelle
target
Funktion des Threads profilieren , die derthreading.Thread.run()
Aufruf ausführt. Aber wie ich in der Antwort sagte, lohnt es sich wahrscheinlich nicht, Thread zu unterordnen, da Code von Drittanbietern ihn nicht verwendet und stattdessen verwendetthreading.setprofile()
.Das Python-Wiki ist eine großartige Seite für die Profilerstellung von Ressourcen: http://wiki.python.org/moin/PythonSpeed/PerformanceTips#Profiling_Code
ebenso wie die Python-Dokumente: http://docs.python.org/library/profile.html
Wie von Chris Lawlor gezeigt, ist cProfile ein großartiges Werkzeug und kann leicht zum Drucken auf dem Bildschirm verwendet werden:
oder zu archivieren:
PS> Wenn Sie Ubuntu verwenden, stellen Sie sicher, dass Sie das Python-Profil installieren
Wenn Sie in eine Datei ausgeben, können Sie mit den folgenden Tools schöne Visualisierungen erhalten
PyCallGraph: ein Werkzeug Aufrufgraphen Bilder erstellen zu
installieren:
Lauf:
Aussicht:
Sie können verwenden, was Sie möchten, um die PNG-Datei anzuzeigen, ich habe Gimp verwendet
Leider bekomme ich oft
Punkt: Die Grafik ist zu groß für Kairo-Renderer-Bitmaps. Skalierung um 0,257079 passend
Das macht meine Bilder ungewöhnlich klein. Also erstelle ich im Allgemeinen SVG-Dateien:
PS> Stellen Sie sicher, dass Sie graphviz installieren (das das Punktprogramm bereitstellt):
Alternative Grafik mit gprof2dot über @maxy / @quodlibetor:
quelle
@ Maxys Kommentar zu dieser Antwort hat mir so geholfen, dass ich denke, dass sie eine eigene Antwort verdient: Ich hatte bereits von cProfile generierte .pstats-Dateien und wollte die Dinge nicht mit pycallgraph erneut ausführen, also habe ich gprof2dot verwendet und bin hübsch geworden svgs:
und BLAM!
Es wird Punkt verwendet (das gleiche, was Pycallgraph verwendet), sodass die Ausgabe ähnlich aussieht. Ich habe den Eindruck, dass gprof2dot weniger Informationen verliert:
quelle
pwd
/gprof2dot/gprof2dot.py $ HOME / bin (oder verwenden Sie in den meisten Shells ln -s $ PWD / gprof2dot / gprof2dot.py ~ / bin - der schwerwiegende Akzent wird zuerst als Formatierung verwendet Ausführung).ln
die Argumentationsreihenfolge fast jedes Mal falsch.Bei der Recherche zu diesem Thema bin ich auf ein praktisches Tool namens SnakeViz gestoßen . SnakeViz ist ein webbasiertes Tool zur Visualisierung von Profilen. Es ist sehr einfach zu installieren und zu verwenden. Die übliche Art, wie ich es benutze, besteht darin, eine
%prun
Statistikdatei mit SnakeViz zu generieren und diese dann zu analysieren.Die hauptsächlich verwendete Technik ist das unten gezeigte Sunburst-Diagramm , in dem die Hierarchie der Funktionsaufrufe als Schichten von Bögen und Zeitinformationen angeordnet ist, die in ihren Winkelbreiten codiert sind.
Das Beste ist, dass Sie mit dem Diagramm interagieren können. Zum Vergrößern kann man beispielsweise auf einen Bogen klicken, und der Bogen und seine Nachkommen werden als neuer Sunburst vergrößert, um weitere Details anzuzeigen.
quelle
Einfachster und schnellster Weg, um herauszufinden, wohin die ganze Zeit geht.
Zeichnet ein Kreisdiagramm in einem Browser. Das größte Stück ist die Problemfunktion. Sehr einfach.
quelle
Ich denke, das
cProfile
ist großartig für die Profilerstellung, währendkcachegrind
es großartig ist, um die Ergebnisse zu visualisieren. Daspyprof2calltree
Dazwischen übernimmt die Dateikonvertierung.So installieren Sie die erforderlichen Tools (zumindest unter Ubuntu):
Das Ergebnis:
quelle
brew install qcachegrind
und ersetzen jeweilskcachegrind
mitqcachegrind
in der Beschreibung für eine erfolgreiche Profilerstellung.export QT_X11_NO_MITSHM=1
Erwähnenswert ist auch der GUI cProfile Dump Viewer RunSnakeRun . Sie können damit sortieren und auswählen und so die relevanten Teile des Programms vergrößern. Die Größe der Rechtecke im Bild ist proportional zur benötigten Zeit. Wenn Sie mit der Maus über ein Rechteck fahren, wird dieser Aufruf in der Tabelle und überall auf der Karte hervorgehoben. Wenn Sie auf ein Rechteck doppelklicken, wird dieser Teil vergrößert. Es zeigt Ihnen, wer diesen Teil anruft und wie dieser Teil anruft.
Die beschreibenden Informationen sind sehr hilfreich. Es zeigt Ihnen den Code für dieses Bit, der hilfreich sein kann, wenn Sie mit integrierten Bibliotheksaufrufen arbeiten. Hier erfahren Sie, in welcher Datei und in welcher Zeile Sie den Code finden.
Ich möchte auch darauf hinweisen, dass das OP "Profiling" sagte, aber es scheint, dass er "Timing" meinte. Beachten Sie, dass Programme beim Profilieren langsamer ausgeführt werden.
quelle
Ein nettes Profiling-Modul ist der line_profiler (wird mit dem Skript kernprof.py aufgerufen). Es kann hier heruntergeladen werden .
Nach meinem Verständnis gibt cProfile nur Informationen über die Gesamtzeit, die in jeder Funktion verbracht wurde. Einzelne Codezeilen sind also nicht zeitgesteuert. Dies ist ein Problem im wissenschaftlichen Rechnen, da oft eine einzelne Zeile viel Zeit in Anspruch nehmen kann. Wie ich mich erinnere, hat cProfile auch nicht die Zeit erfasst, die ich in "numpy.dot" verbracht habe.
quelle
Ich habe kürzlich Thunfisch zur Visualisierung der Python-Laufzeit und zum Importieren von Profilen erstellt. Dies kann hier hilfreich sein.
Installieren mit
Erstellen Sie ein Laufzeitprofil
oder ein Importprofil (Python 3.7+ erforderlich)
Führen Sie dann einfach Thunfisch für die Datei aus
quelle
Profil
line_profiler
(hier bereits vorgestellt) auch inspiriertpprofile
, was beschrieben wird als:Es bietet Zeilengranularität, da
line_profiler
es reines Python ist, als eigenständiger Befehl oder als Modul verwendet werden kann und sogar Dateien im Callgrind-Format generieren kann, mit denen es einfach analysiert werden kann[k|q]cachegrind
.vprof
Es gibt auch vprof , ein Python-Paket, das wie folgt beschrieben wird:
quelle
Es gibt viele gute Antworten, aber sie verwenden entweder die Befehlszeile oder ein externes Programm zum Profilieren und / oder Sortieren der Ergebnisse.
Ich habe wirklich eine Möglichkeit verpasst, die ich in meiner IDE (eclipse-PyDev) verwenden konnte, ohne die Befehlszeile zu berühren oder etwas zu installieren. Hier ist es also.
Profilerstellung ohne Kommandozeile
Weitere Informationen finden Sie in den Dokumenten oder anderen Antworten.
quelle
Nach der Antwort von Joe Shaw, dass Multithread-Code nicht wie erwartet funktioniert, stellte ich fest, dass die
runcall
Methode in cProfile lediglich den profilierten Funktionsaufruf ausführtself.enable()
undself.disable()
aufruft, sodass Sie dies einfach selbst tun und den gewünschten Code dazwischen haben können minimale Störung des vorhandenen Codes.quelle
cprofile.py
den Quellcode zeigt, dass genau das derruncall()
Fall ist. Spezifischere sein, nachdem sie mit einem Profil Instanzprof = cprofile.Profile()
, sofort anrufenprof.disable()
, und dann fügen Sie einfachprof.enable()
undprof.disable()
Anrufe rund um den Abschnitt des Codes Sie profiliert werden soll.In Virtaals Quelle gibt es eine sehr nützliche Klasse und einen Dekorator, die das Profiling (auch für bestimmte Methoden / Funktionen) sehr einfach machen können. Die Ausgabe kann dann in KCacheGrind sehr bequem angezeigt werden.
quelle
cProfile eignet sich hervorragend für die schnelle Profilerstellung, aber die meiste Zeit endete es für mich mit den Fehlern. Die Funktion runctx löst dieses Problem, indem sie die Umgebung und die Variablen korrekt initialisiert. Ich hoffe, sie kann für jemanden nützlich sein:
quelle
Wenn Sie einen kumulativen Profiler erstellen möchten, dh die Funktion mehrmals hintereinander ausführen und die Summe der Ergebnisse anzeigen möchten.
Sie können diesen
cumulative_profiler
Dekorateur verwenden:Es ist Python> = 3.6-spezifisch, aber Sie können es entfernen,
nonlocal
damit es auf älteren Versionen funktioniert.Beispiel
Profilerstellung der Funktion
baz
baz
lief 5 mal und druckte dies:Angabe der Häufigkeit
quelle
Die reine (und einfachste) Lösung für den Fall, dass all diese ausgefallenen Benutzeroberflächen nicht installiert oder ausgeführt werden können:
Ignorieren Sie sie
cProfile
vollständig und ersetzen Sie sie durchpyinstrument
, um den Aufrufbaum direkt nach der Ausführung zu erfassen und anzuzeigen.Installieren:
Profil und Anzeigeergebnis:
Funktioniert mit Python2 und 3.
[EDIT] Die Dokumentation der API zum Profilieren nur eines Teils des Codes finden Sie hier .
quelle
Ich verwende yappi ( https://github.com/sumerc/yappi ). Dies ist besonders nützlich in Kombination mit einem RPC-Server, auf dem Sie (auch nur zum Debuggen) eine Methode zum Starten, Stoppen und Drucken von Profilinformationen registrieren, z. B. auf folgende Weise:
Wenn Ihr Programm funktioniert, können Sie den Profiler jederzeit starten, indem Sie die
startProfiler
RPC-Methode aufrufen und Profilinformationen durch Aufrufen in eine ProtokolldateiprintProfiler
kopieren (oder die rpc-Methode ändern, um sie an den Aufrufer zurückzugeben), und folgende Ausgabe erhalten:Es ist möglicherweise nicht sehr nützlich für kurze Skripte, hilft jedoch bei der Optimierung von Prozessen vom Servertyp, insbesondere da die
printProfiler
Methode im Laufe der Zeit mehrmals aufgerufen werden kann, um z. B. verschiedene Programmnutzungsszenarien zu profilieren und zu vergleichen.In neueren Versionen von yappi funktioniert der folgende Code:
quelle
def printProfiler(): if not yappi_available: return stats = yappi.get_func_stats() stats.print_all(columns={0:("name",90), 1:("ncall", 5), 2:("tsub", 8), 3:("ttot", 8), 4:("tavg",8)})
(OK, nachdem ich einige Male versucht habe, einen Codeblock in den Kommentar einzufügen, den ich aufgegeben habe. Dies ist für eine programmierorientierte Q & A-Site unglaublich schwierig. )Ein neues Tool zur Profilerstellung in Python ist PyVmMonitor: http://www.pyvmmonitor.com/
Es hat einige einzigartige Funktionen wie
Hinweis: Es ist kommerziell, aber kostenlos für Open Source.
quelle
gprof2dot_magic
Magische Funktion
gprof2dot
zum Profilieren einer Python-Anweisung als DOT-Diagramm in JupyterLab oder Jupyter Notebook.GitHub-Repo: https://github.com/mattijn/gprof2dot_magic
Installation
Stellen Sie sicher, dass Sie das Python-Paket haben
gprof2dot_magic
.Seine Abhängigkeiten
gprof2dot
undgraphviz
werden ebenfalls installiertVerwendungszweck
Laden Sie zuerst das
gprof2dot_magic
Modul, um die magische Funktion zu aktivierenund profilieren Sie dann eine beliebige Zeilenanweisung als DOT-Diagramm als solches:
quelle
https://github.com/amoffat/Inspect-Shell
Sie könnten das (und Ihre Armbanduhr) verwenden.
quelle
So fügen Sie https://stackoverflow.com/a/582337/1070617 hinzu :
Ich habe dieses Modul geschrieben, mit dem Sie cProfile verwenden und seine Ausgabe einfach anzeigen können. Mehr hier: https://github.com/ymichael/cprofilev
Siehe auch: http://ymichael.com/2014/03/08/profiling-python-with-cprofile.html, wie Sie die gesammelten Statistiken verstehen können.
quelle
Dies hängt davon ab, was Sie bei der Profilerstellung sehen möchten. Einfache Zeitmetriken können durch (bash) angegeben werden.
Sogar '/ usr / bin / time' kann mithilfe des Flags '--verbose' detaillierte Metriken ausgeben.
Um die von jeder Funktion angegebenen Zeitmetriken zu überprüfen und besser zu verstehen, wie viel Zeit für Funktionen aufgewendet wird, können Sie das in Python integrierte cProfile verwenden.
Bei detaillierteren Metriken wie der Leistung ist die Zeit nicht die einzige Metrik. Sie können sich Gedanken über Speicher, Threads usw. machen.
Profiling-Optionen:
1. line_profiler ist ein weiterer Profiler, der häufig verwendet wird, um Timing-Metriken zeilenweise herauszufinden.
2. memory_profiler ist ein Tool zum Profilieren der Speichernutzung.
3. Heapy (aus dem Projekt Guppy) Profilieren Sie, wie Objekte im Heap verwendet werden.
Dies sind einige der häufigsten, die ich benutze. Wenn Sie jedoch mehr erfahren möchten, lesen Sie dieses Buch. Es ist ein ziemlich gutes Buch, wenn Sie mit Blick auf die Leistung beginnen. Sie können zu fortgeschrittenen Themen über die Verwendung von Cython und JIT (Just-in-Time) kompiliertem Python übergehen.
quelle
Mit einem statistischen Profiler wie austin ist keine Instrumentierung erforderlich, sodass Sie Profildaten aus einer Python-Anwendung einfach mit abrufen können
Die Rohausgabe ist nicht sehr nützlich, aber Sie können sie an flamegraph.pl weiterleiten , um eine Flammengraphendarstellung dieser Daten zu erhalten, aus der hervorgeht, wo die Zeit (gemessen in Mikrosekunden in Echtzeit) verbracht wird.
quelle
Zum schnellen Abrufen von Profilstatistiken für Ihre Codefragmente auf einem IPython-Notizbuch. Man kann line_profiler und memory_profiler direkt in ihre Notizbücher einbetten.
Kapiert!
Lade es!
Benutze es!
%Zeit
Gibt:
% timeit
% beschneiden
Gibt:
% memit
Gibt:
% lprun
Gibt:
quelle
Es gibt auch einen statistischen Profiler namens
statprof
. Es ist ein Sampling-Profiler, der Ihrem Code nur minimalen Overhead hinzufügt und zeilenbasierte (nicht nur funktionsbasierte) Timings liefert. Es eignet sich eher für weiche Echtzeitanwendungen wie Spiele, ist jedoch möglicherweise weniger präzise als cProfile.Die Version in pypi ist ein bisschen alt, kann es so installieren , um mit
pip
durch die Angabe der git - Repository :Sie können es so ausführen:
Siehe auch https://stackoverflow.com/a/10333592/320036
quelle
Ich habe gerade meinen eigenen Profiler entwickelt, der von pypref_time inspiriert ist:
https://github.com/modaresimr/auto_profiler
Durch Hinzufügen eines Dekorateurs wird ein Baum zeitaufwändiger Funktionen angezeigt
@Profiler(depth=4, on_disable=show)
Beispiel
Beispielausgabe
quelle
Wenn ich nicht root auf dem Server bin, verwende ich lsprofcalltree.py und führe mein Programm folgendermaßen aus:
Dann kann ich den Bericht mit jeder Callgrind-kompatiblen Software wie qcachegrind öffnen
quelle