Dokumentation
Pyinstrument ist ein Python-Profiler. Ein Profiler ist ein Tool, das Ihnen hilft, Ihren Code zu optimieren – also schneller zu machen. Um die größte Geschwindigkeitssteigerung zu erzielen, sollten Sie sich auf den langsamsten Teil Ihres Programms konzentrieren. Pyinstrument hilft Ihnen, es zu finden!
☕️ Sie wissen nicht, wo Sie anfangen sollen? Schauen Sie sich dieses Video-Tutorial von Calmcode.io an!
pip install pyinstrument
Pyinstrument unterstützt Python 3.8+.
Um Pyinstrument von einem Git-Checkout aus auszuführen, gibt es einen Build-Schritt. Weitere Informationen finden Sie unter „Mitwirken“.
Um zu erfahren, wie Sie pyinstrument verwenden, oder um die Referenz zu überprüfen, gehen Sie zur Dokumentation.
pyinstrument script.py
verwenden, wobei script.py
eine mit pickle
serialisierte Klasse enthält, können Fehler auftreten, da die Serialisierungsmaschinerie nicht weiß, wo sich __main__
befindet. In diesem Problem finden Sie Problemumgehungen 11. Oktober 2024
Viele Verbesserungen am HTML-Renderer!
Zeitleistenmodus – Sehen Sie sich eine interaktive lineare Zeitleiste an und zoomen Sie hinein!
Der HTML-Modus verfügt jetzt über interaktive Optionen, sodass keine vorherige Einstellung erforderlich ist.
Das Design des HTML-Seitenheaders wurde optimiert.
Die HTML-Aufrufstapelansicht unterstützt die Pfeiltastennavigation.
Die Art und Weise, wie „Bibliotheks“-Code erkannt wird, wurde geändert. Wenn zuvor die Zeichenfolge „/lib/“ im Dateipfad vorkam, wurde dies als Bibliothekscode betrachtet (und standardmäßig ausgeblendet). Jetzt erfasst pyinstrument die Pfade der Python-Installation und aller aktiven Virtualenv/Conda-Umgebungen zur Profilzeit. Dort gespeicherte Dateien gelten als Bibliothek. Das dürfte zu weniger Fehlalarmen führen.
Aufrufe von Profiler.start() können jetzt einen target_description-Parameter übergeben, der in der Profilanzeige angezeigt wird.
Weitere Informationen zu den neuen Funktionen finden Sie in meinem Blogbeitrag.
6. September 2024
glom
unter Python 3.12 oder höher nicht importieren kann, wodurch das locals()-Diktat mutiert wird. (#336)UnicodeDecodeError
verursachte (#330)5. August 2024
2. August 2024
1. August 2024
with
Block oder einen Funktions-/Methoden-Decorator verwenden. Dadurch wird der Code profiliert und eine kurze Anzeige im Terminal ausgegeben. (#327)flat
Argument hinzu, um eine flache Liste von Funktionen darzustellen (#294)26. Januar 2024
show_all
zu Profiler.output_html hinzu8. November 2023
%pyinstrument
(#278)12. Oktober 2023
-c
hinzu, die die Profilerstellung von Code direkt über die Befehlszeile ermöglicht, wie z. B. python -c
. (#271)Profiler.write_html
hinzu, um HTML-Ausgaben direkt in eine Datei zu schreiben. (#266)7. September 2023
1. September 2023
22. Juli 2023
[X frames hidden]
in der Ausgabe angezeigt wurden, wenn Frames aufgrund von __tracebackhide__
gelöscht wurden (#255)None
anzeigte (#254)5. Juni 2023
-p flat
in der Befehlszeile aktiviert werden kann. Dieser Modus zeigt den schwersten Frame gemessen an der Eigenzeit an, was in einigen Codebasen nützlich sein kann. (#240)pstats
Dateien zu speichern. Dies ist das Dateiformat, das von cprofile in der stdlib verwendet wird. Es ist weniger detailliert als Pyinstrument-Profile, aber mit mehr Tools kompatibel. (#236)--show-all
– pyinstrument entfernt keine Python-internen Frames mehr, wenn diese Option angegeben wird. (#239)5. November 2022
__traceback_hide__
festlegen, werden jetzt aus der Ausgabe entfernt (#217)--async_mode=enabled
ausführen. (#212)21. August 2022
--interval
(Sekunden, Standard 0,001) hinzu, um das Intervall zu ändern, in dem pyinstrument ein Programm abtastet. Dies ist nützlich für Programme mit langer Laufzeit, bei denen eine Vergrößerung des Intervalls den Speicheraufwand verringert. Fügt eine Befehlszeilenoption -p
--render-option
hinzu, die das beliebige Festlegen von Renderoptionen ermöglicht. Auf diese Weise können Sie Optionen wie filter_threshold
über die Befehlszeile festlegen, indem Sie beispielsweise pyinstrument -p processor_options.filter_threshold=0
ausführen.
Hier ist die Hilfeausgabe für die Option:
-p RENDER_OPTION, --render-option=RENDER_OPTION
options to pass to the renderer, in the format
'flag_name' or 'option_name=option_value'. For
example, to set the option 'time', pass '-p
time=percent_of_total'. To pass multiple options, use
the -p option multiple times. You can set processor
options using dot-syntax, like '-p
processor_options.filter_threshold=0'. option_value is
parsed as a JSON value or a string.
Integriert die Möglichkeit, Zeiten in der Konsolenausgabe als Prozentsätze statt als absolute Zeiten anzuzeigen. Verwenden Sie die ConsoleRenderer-Option time='percent_of_total'
oder verwenden Sie in der Befehlszeile -p
, wie pyinstrument -p time=percent_of_total
.
Fügt Befehlszeilenoptionen zum Laden und Speichern von Pyinstrument-Sitzungen hinzu. Sie können die Rohdaten für eine Pyinstrument-Sitzung mit -r session
speichern, beispielsweise pyinstrument -r session -o session.pyisession myscript.py
. Das Laden erfolgt über --load
, z. B. pyinstrument --load session.pyisession
.
Das Ausgabeformat der Befehlszeile wird aus der Ausgabedateierweiterung -o
abgeleitet. Wenn Sie also pyinstrument -o profile.html myscript.py
ausführen, müssen Sie -r html
nicht angeben, pyinstrument verwendet automatisch den HTML-Renderer. Oder wenn Sie pyinstrument -o profile.pyisession myscript.py
ausführen, wird ein unformatiertes Sitzungsobjekt gespeichert.
Fügt der Dokumentation Anwendungsbeispiele für FastAPI und Pytest hinzu.
Behebt einen Fehler, der NotImplementedError verursacht, wenn async_mode=strict
verwendet wird.
Fügt Unterstützung für Python 3.11 hinzu
%load_ext pyinstrument
oben in Ihrem Notizbuch und dann %%pyinstrument
in der Zelle, die Sie profilieren möchten.pyinstrument -r speedscope
und laden Sie es in die Speedscope-Web-App hoch.PYINSTRUMENT_PROFILE_DIR_RENDERER
verwenden.Async-Unterstützung! Pyinstrument erkennt jetzt, wenn eine asynchrone Aufgabe auf eine Wartezeit trifft, und verfolgt die außerhalb des asynchronen Kontexts verbrachte Zeit in dieser Wartezeit.
Hier ist zum Beispiel ein einfaches Skript mit einer asynchronen Aufgabe, die einen Ruhezustand ausführt:
import asyncio
from pyinstrument import Profiler
async def main ():
p = Profiler ( async_mode = 'disabled' )
with p :
print ( 'Hello ...' )
await asyncio . sleep ( 1 )
print ( '... World!' )
p . print ()
asyncio . run ( main ())
Vor Pyinstrument 4.0.0 sahen wir nur die in der Ausführungsschleife verbrachte Zeit, etwa so:
_ ._ __/__ _ _ _ _ _/_ Recorded: 18:33:03 Samples: 2
/_//_/// /_ / //_// / //_'/ // Duration: 1.006 CPU time: 0.001
/ _/ v3.4.2
Program: examples/async_example_simple.py
1.006 _run_once asyncio/base_events.py:1784
└─ 1.005 select selectors.py:553
[3 frames hidden] selectors,
1.005 kqueue.control :0
Mit Pyinstrument 4.0.0 erhalten wir nun:
_ ._ __/__ _ _ _ _ _/_ Recorded: 18:30:43 Samples: 2
/_//_/// /_ / //_// / //_'/ // Duration: 1.007 CPU time: 0.001
/ _/ v4.0.0
Program: examples/async_example_simple.py
1.006 main async_example_simple.py:4
└─ 1.005 sleep asyncio/tasks.py:641
[2 frames hidden] asyncio
1.005 [await]
Weitere Informationen finden Sie in der Dokumentation zur asynchronen Profilerstellung und in der Eigenschaft Profiler.async_mode.
Pyinstrument verfügt über eine Dokumentationsseite, einschließlich vollständiger Python-API-Dokumente!
--show
, --show-regex
und --show-all
in der Befehlszeile ignoriert wurden.timeline
Option (boolean) zu den Profiler-Methoden output_html()
und open_in_browser()
hinzugefügt.pyinstrument -m module
behoben, bei dem pyinstrument keine Module im aktuellen Verzeichnis finden konnte.Python -> C -> Python
wird als Python -> Python
aufgezeichnet, aber Python -> Python -> C
wird korrekt zugeordnet. (#103)<__array_function__ internals>
-Frames, die in Berichten als App-Code angezeigt werden--show
und --show-regex
hinzu, um bestimmte Dateien für die Anzeige zu markieren. Dies hilft bei der Profilierung bestimmter Module, während andere ausgeblendet werden. Zum Beispiel pyinstrument --show '*/sympy/*' script.py
.Pyinstrument verbirgt jetzt Spuren in Bibliotheken, die Sie standardmäßig verwenden. Anstatt Ihnen also Unmengen von Frames zu zeigen, die die Interna von etwas Externem, z. B. urllib, durchlaufen, können Sie sich auf Ihren Code konzentrieren.
Vor | Nach |
---|---|
Um zum alten Verhalten zurückzukehren, verwenden Sie --show-all
in der Befehlszeile.
Es werden „Eintritts“-Frames versteckter Gruppen angezeigt, sodass Sie wissen, welcher Anruf das Problem darstellt
Es werden auch sehr langsame Frames in den Gruppen angezeigt, z. B. der „read“-Aufruf auf dem Socket
Der Anwendungscode wird in der Konsole hervorgehoben
Zusätzliche Metriken werden oben im Trace angezeigt – Zeitstempel, Anzahl der Proben, Dauer, CPU-Zeit
Versteckter Code wird durch die Optionen --hide
oder --hide-regex
gesteuert – passend zum Pfad der Codedateien.
--hide=EXPR glob-style pattern matching the file paths whose
frames to hide. Defaults to '*/lib/*'.
--hide-regex=REGEX regex matching the file paths whose frames to hide.
Useful if --hide doesn't give enough control.
Die Ausgabe einer Zeitleiste wird über die Befehlszeile unterstützt.
-t, --timeline render as a timeline - preserve ordering and don't
condense repeated calls
Da es jetzt einige Rendering-Optionen gibt, können Sie mit --load-prev
eine frühere Profilerstellungssitzung laden – pyinstrument behält die letzten 10 Sitzungen.
Verborgene Gruppen können auch in Anwendungscode zurückgerufen werden, der wie folgt aussieht:
(intern) Bei der Aufzeichnung von Zeitleisten sind die Frame-Bäume jetzt vollständig linear, was die Erstellung hochpräziser Frame-Diagramme ermöglicht.
(intern) Der HTML-Renderer wurde als Vue.js-App umgeschrieben. Alle Konsolenverbesserungen gelten auch für die HTML-Ausgabe, außerdem ist sie interaktiv.
(intern) Viele Unit- und Integrationstests hinzugefügt!
Huch! Siehe #49 für die blutigen Details. Ich hoffe es gefällt dir.
Recorders
wurden entfernt. Die Frame-Aufzeichnung erfolgt jetzt innerhalb des Profiler
Objekts. Dies bedeutet, dass die „Rahmen“-Objekte allgemeineren Zwecken dienen, was den Weg ebnet für ...--version
hinzufügen Unterstützung für JSON-Ausgabe hinzugefügt. Verwenden Sie pyinstrument --renderer=json scriptfile.py
. PR
@iddan hat mithilfe der JSON-Ausgabe einen interaktiven Viewer zusammengestellt!
Wenn Sie pyinstrument --html
ausführen und die Ausgabe nicht in eine Datei weiterleiten, schreibt pyinstrument die Konsolenausgabe in eine temporäre Datei und öffnet diese in einem Browser.
-m
, z. B. pyinstrument -m module_name
! PR Pyinstrument kann jetzt in einem with
Block verwendet werden.
Zum Beispiel:
profiler = pyinstrument.Profiler()
with profiler:
# do some work here...
print(profiler.output_text())
Middleware-Fix für ältere Versionen von Django
Pyinstrument verwendet einen neuen Profilierungsmodus . Anstatt Signale zu verwenden, verwendet Pyintrument einen neuen statistischen Profiler, der auf PyEval_SetProfile basiert. Dies bedeutet keine Haupt-Thread-Beschränkung mehr, keine E/A-Fehler mehr bei der Verwendung von Pyinstrument und keine Notwendigkeit für einen separaten „Setprofile“-Modus!
Renderer . Benutzer können Pyinstrument anpassen, um alternative Renderer mit dem Argument renderer
in Profiler.output()
oder mit dem Argument --renderer
in der Befehlszeile zu verwenden.
Blockflöten . Um andere Anwendungsfälle von Pyinstrument (z. B. Flammendiagramme) zu unterstützen, verfügt Pyinstrument jetzt über einen „Timeline“-Recordermodus. In diesem Modus werden erfasste Frames linear aufgezeichnet, sodass die Programmausführung auf einer Zeitleiste angezeigt werden kann.
pyinstrument
Befehl. Sie können jetzt Python-Skripte über die Shell profilieren, indem Sie $ pyinstrument script.py
ausführen. Dies entspricht jetzt python -m pyinstrument
. Danke @asmeurer!Anwendungscode wird in HTML-Traces hervorgehoben, um ihn leichter erkennen zu können
Option PYINSTRUMENT_PROFILE_DIR
zur Django-Schnittstelle hinzugefügt, die Profile aller Anfragen in einer Datei im angegebenen Ordner protokolliert. Nützlich für die Profilerstellung von API-Aufrufen.
Option PYINSTRUMENT_USE_SIGNAL
zur Django-Schnittstelle hinzugefügt, zur Verwendung, wenn der Signalmodus Probleme bereitet.
So richten Sie eine Entwicklungsumgebung ein:
virtualenv --python=python3 env
. env/bin/activate
pip install --upgrade pip
pip install -r requirements-dev.txt
pre-commit install --install-hooks
So erhalten Sie eine Beispielausgabe:
pyinstrument examples/wikipedia_article_word_count.py
So führen Sie die Tests aus:
pytest
So führen Sie Flusenprüfungen lokal durch:
pre-commit run --all-files
Einige der Pre-Commit-Prüfungen, wie z. B. isort
oder black
, beheben die gefundenen Probleme automatisch. Wenn der obige Befehl also einen Fehler zurückgibt, versuchen Sie es erneut, es könnte beim zweiten Mal erfolgreich sein :)
Die Ausführung aller Prüfungen kann langsam sein, daher können Sie die Prüfungen auch einzeln ausführen, z. B. um Quellcode zu formatieren, der isort
oder black
-Prüfungen nicht besteht:
pre-commit run --all-files isort
pre-commit run --all-files black
So diagnostizieren Sie, warum pyright
fehlschlagen:
pre-commit run --all-files pyright
Der HTML-Renderer funktioniert, indem er eine JSON-Darstellung des Beispiels mit einem Javascript-„Bundle“ in eine HTML-Datei einbettet, die in jedem Webbrowser angezeigt werden kann.
Um den HTML-Renderer-Stil zu bearbeiten, gehen Sie wie folgt vor:
cd html_renderer
npm ci
npm run serve
Wenn es ohne ein window.profileSession
Objekt der obersten Ebene gestartet wird, ruft es ein Beispielprofil ab, damit Sie damit arbeiten können.
So kompilieren Sie die JS-App und bündeln sie wieder im Python-Tool pyinstrument:
bin/build_js_bundle.py [--force]