Documentation
Pyinstrument est un profileur Python. Un profileur est un outil pour vous aider à optimiser votre code et à le rendre plus rapide. Pour obtenir la plus grande augmentation de vitesse, vous devez vous concentrer sur la partie la plus lente de votre programme. Pyinstrument vous aide à le trouver !
☕️ Vous ne savez pas par où commencer ? Regardez ce didacticiel vidéo de calmcode.io !
pip install pyinstrument
Pyinstrument prend en charge Python 3.8+.
Pour exécuter Pyinstrument à partir d'une caisse git, il y a une étape de construction. Jetez un œil à Contribuer pour plus d’informations.
Pour apprendre à utiliser pyinstrument ou pour vérifier la référence, rendez-vous sur la documentation.
pyinstrument script.py
où script.py
contient une classe sérialisée avec pickle
, vous pouvez rencontrer des erreurs car la machine de sérialisation ne sait pas où se trouve __main__
. Voir ce problème pour les solutions de contournement 11 octobre 2024
De nombreuses améliorations apportées au moteur de rendu HTML !
Mode Chronologie : visualisez et zoomez sur une chronologie linéaire interactive !
Le mode HTML propose désormais des options interactives, plutôt que de nécessiter une configuration initiale.
Rationalisation de la conception de l'en-tête de la page HTML.
La vue de la pile d’appels HTML prend en charge la navigation par touches fléchées.
La façon dont le code « bibliothèque » est détecté a été modifiée. Auparavant, si la chaîne « /lib/ » apparaissait dans le chemin du fichier, cela était considéré comme du code de bibliothèque (et réduit par défaut). Désormais, pyinstrument capture les chemins d'installation de Python et tout environnement virtualenv/conda actif au moment du profil. Les fichiers qui y sont stockés sont considérés comme une bibliothèque. Cela devrait donner moins de faux positifs.
Les appels à profiler.start() peuvent désormais transmettre un paramètre target_description, qui est affiché dans la lecture du profil.
Consultez mon article de blog pour plus d'informations sur les nouvelles fonctionnalités.
6 septembre 2024
glom
sur Python 3.12 ou version ultérieure, qui mute le dict locals(). (#336)UnicodeDecodeError
sur certaines plateformes (#330)5 août 2024
2 août 2024
1er août 2024
with
ou un décorateur de fonction/méthode. Cela profilera le code et imprimera une courte lecture dans le terminal. (#327)flat
à la sortie de la console, pour présenter une liste plate de fonctions (#294)26 janvier 2024
show_all
à Profiler.output_html8 novembre 2023
%pyinstrument
(#278)12 octobre 2023
-c
, qui permet de profiler le code directement à partir de la ligne de commande, comme python -c
. (#271)Profiler.write_html
, pour écrire directement la sortie HTML dans un fichier. (#266)7 septembre 2023
1 septembre 2023
22 juillet 2023
[X frames hidden]
dans la sortie lorsque les frames étaient supprimées à cause de __tracebackhide__
(#255)None
dans la sortie de la console (#254)5 juin 2023
-p flat
sur la ligne de commande. Ce mode affiche l'image la plus lourde mesurée par le temps propre, ce qui peut être utile dans certaines bases de code. (#240)pstats
. Il s'agit du format de fichier utilisé par cprofile dans stdlib. C'est moins détaillé que les profils pyinstrument, mais il est compatible avec plus d'outils. (#236)--show-all
- pyinstrument ne supprimera plus les cadres internes à Python lorsque cette option est fournie. (#239)5 novembre 2022
__traceback_hide__
seront désormais supprimées de la sortie (#217)--async_mode=enabled
. (#212)21 août 2022
--interval
(secondes, 0,001 par défaut) pour modifier l'intervalle pendant lequel pyinstrument échantillonne un programme. Ceci est utile pour les programmes de longue durée, où l'augmentation de l'intervalle réduit la surcharge de mémoire. Ajoute une option de ligne de commande -p
--render-option
qui permet la définition arbitraire des options de rendu. Cela vous permet de définir des options telles que filter_threshold
à partir de la ligne de commande, en faisant quelque chose comme pyinstrument -p processor_options.filter_threshold=0
.
Voici le résultat de l'aide pour l'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.
Ajoute la possibilité d'afficher les heures dans la sortie de la console sous forme de pourcentages, plutôt que d'heures absolues. Utilisez l'option ConsoleRenderer time='percent_of_total'
, ou sur la ligne de commande, utilisez -p
, comme pyinstrument -p time=percent_of_total
.
Ajoute des options de ligne de commande pour charger et enregistrer les sessions pyinstrument. Vous pouvez enregistrer les données brutes d'une session pyinstrument avec -r session
, comme pyinstrument -r session -o session.pyisession myscript.py
. Le chargement s'effectue via --load
, par exemple pyinstrument --load session.pyisession
.
Le format de sortie de la ligne de commande est déduit de l'extension de fichier de sortie -o
. Donc, si vous faites pyinstrument -o profile.html myscript.py
, vous n'avez pas besoin de fournir -r html
, pyinstrument utilisera automatiquement le moteur de rendu HTML. Ou si vous faites pyinstrument -o profile.pyisession myscript.py
, cela enregistrera un objet de session brut.
Ajoute des exemples d'utilisation pour FastAPI et pytest à la documentation.
Corrige un bug provoquant NotImplementedError lors de l'utilisation de async_mode=strict
.
Ajoute la prise en charge de Python 3.11
%load_ext pyinstrument
en haut de votre bloc-notes, puis %%pyinstrument
dans la cellule que vous souhaitez profiler.pyinstrument -r speedscope
et téléchargez-le sur l'application Web speedscope.PYINSTRUMENT_PROFILE_DIR_RENDERER
.Prise en charge asynchrone ! Pyinstrument détecte désormais lorsqu'une tâche asynchrone atteint une attente et suit le temps passé en dehors du contexte asynchrone sous cette attente.
Ainsi, par exemple, voici un script simple avec une tâche asynchrone qui effectue une mise en veille :
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 ())
Avant Pyinstrument 4.0.0, nous ne voyions que le temps passé dans la boucle d'exécution, comme ceci :
_ ._ __/__ _ _ _ _ _/_ 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
Maintenant, avec pyinstrument 4.0.0, nous obtenons :
_ ._ __/__ _ _ _ _ _/_ 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]
Pour plus d'informations, consultez la documentation sur le profilage asynchrone et la propriété Profiler.async_mode.
Pyinstrument dispose d'un site de documentation, comprenant des documents complets sur l'API Python !
--show
, --show-regex
, --show-all
sur la ligne de commande.timeline
(booléenne) aux méthodes Profiler output_html()
et open_in_browser()
.pyinstrument -m module
, où pyinstrument ne trouvait pas de modules dans le répertoire actuel.Python -> C -> Python
est enregistré comme Python -> Python
, mais Python -> Python -> C
sera attribué correctement. (#103)<__array_function__ internals>
apparaissant comme code d'application dans les rapports--show
et --show-regex
, pour marquer certains fichiers à afficher. Cela permet de profiler des modules spécifiques, tout en masquant les autres. Par exemple, pyinstrument --show '*/sympy/*' script.py
.Pyinstrument masquera désormais les traces dans les bibliothèques que vous utilisez par défaut. Ainsi, au lieu de vous montrer de nombreuses images passant par les composants internes de quelque chose d'externe, par exemple urllib, cela vous permet de vous concentrer sur votre code.
Avant | Après |
---|---|
Pour revenir à l'ancien comportement, utilisez --show-all
sur la ligne de commande.
Les cadres « Entrée » des groupes masqués sont affichés, afin que vous sachiez quel appel pose problème.
Les trames vraiment lentes dans les groupes sont également affichées, par exemple l'appel 'read' sur le socket
Le code de l'application est mis en évidence dans la console
Des mesures supplémentaires sont affichées en haut de la trace : horodatage, nombre d'échantillons, durée, temps CPU
Le code caché est contrôlé par les options --hide
ou --hide-regex
- correspondant au chemin des fichiers de code.
--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.
La sortie d'une chronologie est prise en charge à partir de la ligne de commande.
-t, --timeline render as a timeline - preserve ordering and don't
condense repeated calls
Comme il existe désormais quelques options de rendu, vous pouvez charger une session de profilage précédente en utilisant --load-prev
- pyinstrument conserve les 10 dernières sessions.
Les groupes masqués peuvent également rappeler le code de l'application, qui ressemble à ceci :
(interne) Lors de l'enregistrement des chronologies, les arborescences d'images sont désormais complètement linéaires, ce qui permet la création de graphiques d'images ultra-précis.
(interne) Le moteur de rendu HTML a été réécrit en tant qu'application Vue.js. Toutes les améliorations de la console s'appliquent également à la sortie HTML, qui est en plus interactive.
(interne) De nombreux tests unitaires et d'intégration ajoutés !
Ouais ! Voir #49 pour les détails sanglants. J'espère que vous l'aimerez.
Recorders
ont été supprimés. L'enregistrement d'images est désormais interne à l'objet Profiler
. Cela signifie que les objets « frame » sont plus polyvalents, ce qui ouvre la voie à...--version
Ajout de la prise en charge de la sortie JSON. Utilisez pyinstrument --renderer=json scriptfile.py
. RP
@iddan a mis en place une visionneuse interactive utilisant la sortie JSON !
Lorsque vous exécutez pyinstrument --html
et que vous ne dirigez pas la sortie vers un fichier, pyinstrument écrira la sortie de la console dans un fichier temporaire et l'ouvrira dans un navigateur.
-m
par exemple pyinstrument -m module_name
! RP Pyinstrument peut désormais être utilisé dans un bloc with
.
Par exemple:
profiler = pyinstrument.Profiler()
with profiler:
# do some work here...
print(profiler.output_text())
Correctif middleware pour les anciennes versions de Django
Pyinstrument utilise un nouveau mode de profilage . Plutôt que d'utiliser des signaux, pyintrument utilise un nouveau profileur statistique construit sur PyEval_SetProfile. Cela signifie plus de restriction sur le thread principal, plus d'erreurs d'E/S lors de l'utilisation de Pyinstrument et plus besoin d'un mode séparé plus « setprofile » !
Rendus . Les utilisateurs peuvent personnaliser Pyinstrument pour utiliser des moteurs de rendu alternatifs avec l'argument renderer
sur Profiler.output()
, ou en utilisant l'argument --renderer
sur la ligne de commande.
Enregistreurs . Pour prendre en charge d'autres cas d'utilisation de Pyinstrument (par exemple, les flame charts), pyinstrument dispose désormais d'un mode enregistreur « timeline ». Ce mode enregistre les images capturées de manière linéaire, afin que l'exécution du programme puisse être visualisée sur une chronologie.
pyinstrument
. Vous pouvez désormais profiler les scripts Python à partir du shell en exécutant $ pyinstrument script.py
. C'est maintenant équivalent à python -m pyinstrument
. Merci @asmeurer !Le code de l'application est mis en évidence dans les traces HTML pour le rendre plus facile à repérer
Ajout de l'option PYINSTRUMENT_PROFILE_DIR
à l'interface Django, qui enregistrera les profils de toutes les requêtes dans un fichier du dossier spécifié. Utile pour profiler les appels d'API.
Ajout de l'option PYINSTRUMENT_USE_SIGNAL
à l'interface Django, à utiliser lorsque le mode signal présente des problèmes.
Pour configurer un environnement de développement :
virtualenv --python=python3 env
. env/bin/activate
pip install --upgrade pip
pip install -r requirements-dev.txt
pre-commit install --install-hooks
Pour obtenir un exemple de résultat :
pyinstrument examples/wikipedia_article_word_count.py
Pour exécuter les tests :
pytest
Pour exécuter des contrôles de peluchage localement :
pre-commit run --all-files
Certaines vérifications préalables à la validation, comme isort
ou black
, résoudront automatiquement les problèmes détectés. Donc, si la commande ci-dessus renvoie une erreur, essayez de la réexécuter, elle pourrait réussir une deuxième fois :)
L'exécution de toutes les vérifications peut être lente, vous pouvez donc également exécuter des vérifications individuellement, par exemple pour formater le code source qui échoue aux vérifications isort
ou black
:
pre-commit run --all-files isort
pre-commit run --all-files black
Pour diagnostiquer pourquoi les vérifications pyright
échouent :
pre-commit run --all-files pyright
Le moteur de rendu HTML fonctionne en intégrant une représentation JSON de l'échantillon avec un « bundle » Javascript dans un fichier HTML pouvant être visualisé dans n'importe quel navigateur Web.
Pour modifier le style du moteur de rendu HTML, procédez :
cd html_renderer
npm ci
npm run serve
Lorsqu'il est lancé sans objet window.profileSession
de niveau supérieur, il récupérera un exemple de profil afin que vous puissiez travailler avec lui.
Pour compiler l'application JS et la regrouper dans l'outil python pyinstrument :
bin/build_js_bundle.py [--force]