Project Euler et d'autres concours de codage ont souvent un temps maximum pour s'exécuter ou les gens se vantent de la rapidité d'exécution de leur solution particulière. Avec Python, les approches sont parfois quelque peu compliquées - c'est-à-dire, ajouter du code temporel à __main__
.
Quelle est la bonne façon de déterminer le temps d'exécution d'un programme Python?
python
performance
profiling
time-complexity
Chris Lawlor
la source
la source
Réponses:
Python inclut un profileur appelé cProfile . Il donne non seulement le temps d'exécution total, mais également le temps de chaque fonction séparément, et vous indique combien de fois chaque fonction a été appelée, ce qui permet de déterminer facilement où vous devez effectuer des optimisations.
Vous pouvez l'appeler depuis votre code ou depuis l'interpréteur, comme ceci:
Encore plus utile, vous pouvez invoquer le cProfile lors de l'exécution d'un script:
Pour le rendre encore plus facile, j'ai créé un petit fichier batch appelé 'profile.bat':
Donc tout ce que j'ai à faire est de courir:
Et je reçois ceci:
EDIT: lien mis à jour vers une bonne ressource vidéo de PyCon 2013 intitulée Python Profiling
Also via YouTube .
la source
python -m cProfile -o <out.profile> <script>
), RunSnakeRun , appelé commerunsnake <out.profile>
est inestimable.cprofile
est toujours recommandé plusprofile
.Il y a quelque temps, j'ai fait
pycallgraph
qui génère une visualisation à partir de votre code Python. Edit: j'ai mis à jour l'exemple pour travailler avec 3.3, la dernière version de cette écriture.Après avoir
pip install pycallgraph
installé et installé GraphViz, vous pouvez l'exécuter à partir de la ligne de commande:Ou, vous pouvez profiler des parties particulières de votre code:
L'un ou l'autre générera un
pycallgraph.png
fichier similaire à l'image ci-dessous:la source
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
.Il convient de souligner que l'utilisation du profileur ne fonctionne (par défaut) que sur le thread principal, et vous n'obtiendrez aucune information des autres threads si vous les utilisez. Cela peut être un peu un problème, car cela n'est pas mentionné dans la documentation du profileur .
Si vous souhaitez également profiler les discussions, vous voudrez regarder la
threading.setprofile()
fonction dans les documents.Vous pouvez également créer votre propre
threading.Thread
sous-classe pour le faire:et utilisez cette
ProfiledThread
classe au lieu de la classe standard. Cela pourrait vous donner plus de flexibilité, mais je ne suis pas sûr que cela en vaille la peine, surtout si vous utilisez du code tiers qui n'utiliserait pas votre classe.la source
target
fonction du thread , qui est ce que l'threading.Thread.run()
appel exécute. Mais comme je l'ai dit dans la réponse, cela ne vaut probablement pas la peine de sous-classer Thread, car aucun code tiers ne l'utilisera, et de l'utiliser à la placethreading.setprofile()
.Le wiki python est une excellente page pour le profilage des ressources: http://wiki.python.org/moin/PythonSpeed/PerformanceTips#Profiling_Code
tout comme les documents python: http://docs.python.org/library/profile.html
comme le montre Chris Lawlor, cProfile est un excellent outil et peut facilement être utilisé pour imprimer à l'écran:
ou à déposer:
PS> Si vous utilisez Ubuntu, assurez-vous d'installer le profil python
Si vous sortez dans un fichier, vous pouvez obtenir de belles visualisations en utilisant les outils suivants
PyCallGraph: un outil pour créer des images d'appels graphiques d'
installation:
courir:
vue:
Vous pouvez utiliser ce que vous voulez pour afficher le fichier png, j'ai utilisé gimp
Malheureusement, je reçois souvent
dot: le graphique est trop grand pour les bitmaps du rendu du Caire. Mise à l'échelle par 0,257079 pour s'adapter
ce qui rend mes images particulièrement petites. Je crée donc généralement des fichiers svg:
PS> assurez-vous d'installer graphviz (qui fournit le programme dot):
Graphisme alternatif utilisant gprof2dot via @maxy / @quodlibetor:
la source
Le commentaire de @ Maxy sur cette réponse m'a suffisamment aidé pour que je pense qu'il mérite sa propre réponse: j'avais déjà des fichiers .pstats générés par cProfile et je ne voulais pas réexécuter les choses avec pycallgraph, alors j'ai utilisé gprof2dot et je suis devenu joli svgs:
et BLAM!
Il utilise dot (la même chose que pycallgraph utilise) donc la sortie est similaire. J'ai l'impression que gprof2dot perd cependant moins d'informations:
la source
pwd
/gprof2dot/gprof2dot.py $ HOME / bin (ou utilisez ln -s $ PWD / gprof2dot / gprof2dot.py ~ / bin dans la plupart des shells - l'accent grave est pris comme formatage en premier version).ln
trompe presque à chaque fois.J'ai rencontré un outil pratique appelé SnakeViz lors de la recherche sur ce sujet. SnakeViz est un outil de visualisation de profilage basé sur le Web. Il est très facile à installer et à utiliser. La façon habituelle de l'utiliser est de générer un fichier de statistiques avec
%prun
puis de faire une analyse dans SnakeViz.La principale technique utilisée est le graphique Sunburst, comme illustré ci-dessous, dans lequel la hiérarchie des appels de fonction est organisée sous forme de couches d'arcs et d'informations temporelles codées dans leurs largeurs angulaires.
La meilleure chose est que vous pouvez interagir avec le graphique. Par exemple, pour zoomer, on peut cliquer sur un arc, et l'arc et ses descendants seront agrandis comme un nouveau rayon de soleil pour afficher plus de détails.
la source
Le moyen le plus simple et le plus rapide de trouver où va tout le temps.
Dessine un graphique à secteurs dans un navigateur. La plus grande pièce est la fonction du problème. Très simple.
la source
Je pense que
cProfile
c'est génial pour le profilage, alors quekcachegrind
c'est génial pour visualiser les résultats. L'pyprof2calltree
entre-deux gère la conversion du fichier.Pour installer les outils requis (sur Ubuntu, au moins):
Le résultat:
la source
brew install qcachegrind
et remplacent chacunkcachegrind
avecqcachegrind
dans la description pour un profilage réussi.export QT_X11_NO_MITSHM=1
Il convient également de mentionner le visualiseur de vidage GUI cProfile RunSnakeRun . Il vous permet de trier et de sélectionner, zoomant ainsi sur les parties pertinentes du programme. La taille des rectangles dans l'image est proportionnelle au temps pris. Si vous passez la souris sur un rectangle, il met en évidence cet appel dans le tableau et partout sur la carte. Lorsque vous double-cliquez sur un rectangle, il effectue un zoom avant sur cette partie. Il vous montrera qui appelle cette partie et ce que cette partie appelle.
Les informations descriptives sont très utiles. Il vous montre le code de ce bit qui peut être utile lorsque vous traitez avec des appels de bibliothèque intégrés. Il vous indique quel fichier et quelle ligne pour trouver le code.
Je voudrais également souligner que le PO a dit «profilage», mais il semble qu'il voulait dire «timing». Gardez à l'esprit que les programmes s'exécutent plus lentement lorsqu'ils sont profilés.
la source
J'ai récemment créé du thon pour visualiser le runtime Python et importer des profils; cela peut être utile ici.
Installer avec
Créer un profil d'exécution
ou un profil d'importation (Python 3.7+ requis)
Ensuite, exécutez simplement le thon sur le fichier
la source
Un module de profilage sympa est le line_profiler (appelé en utilisant le script kernprof.py). Il peut être téléchargé ici .
Ma compréhension est que cProfile ne donne que des informations sur le temps total passé dans chaque fonction. Les lignes de code individuelles ne sont donc pas chronométrées. C'est un problème dans le calcul scientifique car souvent une seule ligne peut prendre beaucoup de temps. De plus, si je me souviens bien, cProfile n'a pas saisi le temps que je passais à dire numpy.dot.
la source
pprofile
line_profiler
(déjà présenté ici) également inspirépprofile
, qui est décrit comme:Il fournit une granularité de ligne car
line_profiler
, est pur Python, peut être utilisé comme une commande autonome ou un module, et peut même générer des fichiers au format callgrind qui peuvent être facilement analysés avec[k|q]cachegrind
.vprof
Il existe également vprof , un package Python décrit comme suit :
la source
Il y a beaucoup de bonnes réponses, mais ils utilisent la ligne de commande ou un programme externe pour profiler et / ou trier les résultats.
J'ai vraiment manqué un moyen que je pouvais utiliser dans mon IDE (eclipse-PyDev) sans toucher à la ligne de commande ni installer quoi que ce soit. Alors voilà.
Profilage sans ligne de commande
Voir les documents ou autres réponses pour plus d'informations.
la source
Suite à la réponse de Joe Shaw à propos du code multi-thread pour ne pas fonctionner comme prévu, je me suis dit que la
runcall
méthode dans cProfile fait simplementself.enable()
etself.disable()
appelle autour de l'appel de fonction profilée, donc vous pouvez simplement le faire vous-même et avoir le code que vous voulez entre interférence minimale avec le code existant.la source
cprofile.py
code source de révèle que c'est exactement ce quiruncall()
fait. Plus précis, après avoir créé une instance de profil avecprof = cprofile.Profile()
, appelez immédiatementprof.disable()
, puis ajoutezprof.enable()
etprof.disable()
appelez autour de la section de code que vous souhaitez profiler.Dans la source de Virtaal, il existe une classe et un décorateur très utiles qui peuvent rendre le profilage (même pour des méthodes / fonctions spécifiques) très facile. La sortie peut ensuite être visualisée très confortablement dans KCacheGrind.
la source
cProfile est idéal pour le profilage rapide, mais la plupart du temps, il se terminait pour moi avec des erreurs. La fonction runctx résout ce problème en initialisant correctement l'environnement et les variables, j'espère que cela peut être utile pour quelqu'un:
la source
Si vous voulez créer un profileur cumulatif, c'est-à-dire exécuter la fonction plusieurs fois de suite et regarder la somme des résultats.
vous pouvez utiliser ce
cumulative_profiler
décorateur:c'est spécifique à python> = 3.6, mais vous pouvez le supprimer
nonlocal
pour qu'il fonctionne sur les anciennes versions.Exemple
profiler la fonction
baz
baz
a couru 5 fois et imprimé ceci:spécifiant le nombre de fois
la source
La solution de terminal uniquement (et la plus simple), au cas où toutes ces interfaces utilisateur fantaisistes ne parviennent pas à installer ou à exécuter:
ignorer
cProfile
complètement et le remplacer parpyinstrument
, qui collectera et affichera l'arborescence des appels juste après l'exécution.Installer:
Profil et résultat d'affichage:
Fonctionne avec python2 et 3.
[EDIT] La documentation de l'API, pour le profilage d'une partie seulement du code, peut être trouvée ici .
la source
Ma façon est d'utiliser yappi ( https://github.com/sumerc/yappi ). Il est particulièrement utile combiné avec un serveur RPC où (même juste pour le débogage) vous enregistrez une méthode pour démarrer, arrêter et imprimer des informations de profilage, par exemple de cette manière:
Ensuite, lorsque votre programme fonctionne, vous pouvez démarrer le profileur à tout moment en appelant la
startProfiler
méthode RPC et vider les informations de profilage dans un fichier journal en appelantprintProfiler
(ou modifier la méthode rpc pour la renvoyer à l'appelant) et obtenir une telle sortie:Il peut ne pas être très utile pour les scripts courts, mais aide à optimiser les processus de type serveur, d'autant plus que la
printProfiler
méthode peut être appelée plusieurs fois dans le temps pour profiler et comparer, par exemple, différents scénarios d'utilisation de programme.Dans les versions plus récentes de yappi, le code suivant fonctionnera:
la source
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 après avoir essayé plusieurs fois d'insérer un bloc de code dans le commentaire que j'ai abandonné. c'est incroyablement difficile pour un site de questions / réponses orienté programmation. )PyVmMonitor est un nouvel outil pour gérer le profilage en Python: http://www.pyvmmonitor.com/
Il possède des fonctionnalités uniques telles que
Remarque: c'est commercial, mais gratuit pour l'open source.
la source
gprof2dot_magic
Fonction magique pour
gprof2dot
profiler toute instruction Python sous forme de graphique DOT dans JupyterLab ou Jupyter Notebook.Dépôt GitHub: https://github.com/mattijn/gprof2dot_magic
installation
Assurez-vous que vous disposez du package Python
gprof2dot_magic
.Ses dépendances
gprof2dot
etgraphviz
seront également installéesusage
Pour activer la fonction magique, chargez d'abord le
gprof2dot_magic
modulepuis profilez toute instruction de ligne sous forme de graphique DOT en tant que tel:
la source
https://github.com/amoffat/Inspect-Shell
Vous pouvez utiliser cela (et votre montre-bracelet).
la source
Pour ajouter à https://stackoverflow.com/a/582337/1070617 ,
J'ai écrit ce module qui vous permet d'utiliser cProfile et de visualiser facilement sa sortie. Plus ici: https://github.com/ymichael/cprofilev
Voir également: http://ymichael.com/2014/03/08/profiling-python-with-cprofile.html sur la façon de donner un sens aux statistiques collectées.
la source
Cela dépendra de ce que vous voulez voir du profilage. Des métriques de temps simples peuvent être fournies par (bash).
Même '/ usr / bin / time' peut produire des métriques détaillées en utilisant l'indicateur '--verbose'.
Pour vérifier les métriques de temps données par chaque fonction et pour mieux comprendre combien de temps est consacré aux fonctions, vous pouvez utiliser le cProfile intégré en python.
En entrant dans des mesures plus détaillées telles que les performances, le temps n'est pas la seule mesure. Vous pouvez vous soucier de la mémoire, des threads, etc.
Options de profilage:
1. line_profiler est un autre profileur utilisé couramment pour trouver les métriques de synchronisation ligne par ligne.
2. memory_profiler est un outil pour profiler l'utilisation de la mémoire.
3. tas (du projet Guppy) Profil de la façon dont les objets du tas sont utilisés.
Ce sont quelques-uns des plus courants que j'ai tendance à utiliser. Mais si vous voulez en savoir plus, essayez de lire ce livre. C'est un très bon livre pour commencer avec la performance en tête. Vous pouvez passer à des rubriques avancées sur l'utilisation de python compilé Cython et JIT (Just-in-time).
la source
Avec un profileur statistique comme Austin , aucune instrumentation n'est requise, ce qui signifie que vous pouvez obtenir des données de profilage d'une application Python simplement avec
La sortie brute n'est pas très utile, mais vous pouvez la diriger vers flamegraph.pl pour obtenir une représentation graphique de la flamme de ces données qui vous donne une ventilation de l'endroit où le temps (mesuré en microsecondes en temps réel) est passé.
la source
Pour obtenir des statistiques de profil rapides sur un ordinateur portable IPython. On peut incorporer line_profiler et memory_profiler directement dans leurs cahiers.
Un autre package utile est Pympler . Il s'agit d'un puissant package de profilage capable de suivre les classes, les objets, les fonctions, les fuites de mémoire, etc. Exemples ci-dessous, documents joints.
Tu piges!
Charge le!
Utilise le!
%temps
Donne:
% timeit
% élagage
Donne:
% memit
Donne:
% lprun
Donne:
sys.getsizeof
Renvoie la taille d'un objet en octets.
asizeof () de pympler
pympler.asizeof peut être utilisé pour étudier la quantité de mémoire consommée par certains objets Python. Contrairement à sys.getsizeof, asizeof taille les objets récursivement
tracker de pympler
Suit la durée de vie d'une fonction.
Le package Pympler se compose d'un grand nombre de fonctions hautement utiles pour profiler le code. Tout cela ne peut pas être couvert ici. Voir la documentation jointe pour les implémentations de profil détaillé.
Pympler doc
la source
Il existe également un profileur statistique appelé
statprof
. Il s'agit d'un profileur d'échantillonnage, il ajoute donc une surcharge minimale à votre code et donne des temporisations basées sur la ligne (et pas seulement sur la fonction). Il est plus adapté aux applications logicielles en temps réel comme les jeux, mais peut être moins précis que cProfile.La version dans pypi est un peu ancienne, vous pouvez donc l'installer avec
pip
en spécifiant le dépôt git :Vous pouvez l'exécuter comme ceci:
Voir aussi https://stackoverflow.com/a/10333592/320036
la source
Je viens de développer mon propre profileur inspiré de pypref_time:
https://github.com/modaresimr/auto_profiler
En ajoutant un décorateur, il affichera un arbre de fonctions chronophages
@Profiler(depth=4, on_disable=show)
Exemple
Exemple de sortie
la source
Quand je ne suis pas root sur le serveur, j'utilise lsprofcalltree.py et exécute mon programme comme ceci:
Ensuite, je peux ouvrir le rapport avec n'importe quel logiciel compatible avec callgrind, comme qcachegrind
la source