Question

Euler projet et d'autres concours de codage ont souvent une durée maximale d'exécution ou les gens se vanter de la rapidité de leur solution particulière fonctionne. Avec python, parfois, les approches sont quelque peu kludgey - à savoir l'ajout de code temporel à __main__

.

Qu'est-ce qu'un bon moyen de profil combien de temps un programme Python prend pour exécuter?

Était-ce utile?

La solution

Python comprend un profileur appelé cprofile. Elle ne donne que le temps total de la course, mais aussi de chaque fonction séparément, et vous indique combien de fois chaque fonction a été appelée, le rendant facile à déterminer où vous devriez faire des optimisations.

Vous pouvez appeler à partir de votre code, ou de l'interprète, comme ceci:

import cProfile
cProfile.run('foo()')

Encore plus utile, vous pouvez invoquer le cprofile lors de l'exécution d'un script:

python -m cProfile myscript.py

Pour le rendre encore plus facile, je fait un petit fichier batch appelé « profile.bat »:

python -m cProfile %1

Donc tout ce que je dois faire est de lancer:

profile euler048.py

Et je reçois ceci:

1007 function calls in 0.061 CPU seconds

Ordered by: standard name
ncalls  tottime  percall  cumtime  percall filename:lineno(function)
    1    0.000    0.000    0.061    0.061 <string>:1(<module>)
 1000    0.051    0.000    0.051    0.000 euler048.py:2(<lambda>)
    1    0.005    0.005    0.061    0.061 euler048.py:2(<module>)
    1    0.000    0.000    0.061    0.061 {execfile}
    1    0.002    0.002    0.053    0.053 {map}
    1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler objects}
    1    0.000    0.000    0.000    0.000 {range}
    1    0.003    0.003    0.003    0.003 {sum}

EDIT: lien Mise à jour à une bonne ressource vidéo à partir PyCon 2013 intitulé profilage Python
également via YouTube.

Autres conseils

Il y a quelque temps que je fait pycallgraph qui génère une visualisation à partir de votre code Python. Edit:. J'ai mis à jour l'exemple de travailler avec 3.3, la dernière version de cette écriture

Après un pip install pycallgraph et l'installation GraphViz vous pouvez l'exécuter à partir de la ligne de commande:

pycallgraph graphviz -- ./mypythonscript.py

Ou, vous pouvez profiler certaines parties de votre code:

from pycallgraph import PyCallGraph
from pycallgraph.output import GraphvizOutput

with PyCallGraph(output=GraphvizOutput()):
    code_to_profile()

Soit ces éléments vont générer un fichier pycallgraph.png similaire à l'image ci-dessous:

entrer image description ici

Il est intéressant de souligner que l'utilisation du profileur fonctionne uniquement (par défaut) sur le thread principal, et vous n'obtenir aucune information d'autres sujets si vous les utilisez. Cela peut être un peu Gotcha car il est complètement passé sous silence dans le documentation profileur .

Si vous voulez aussi le profil de threads, vous aurez envie de regarder le titre fonction threading.setprofile() dans la documentation.

Vous pouvez aussi créer votre propre sous-classe threading.Thread pour le faire:

class ProfiledThread(threading.Thread):
    # Overrides threading.Thread.run()
    def run(self):
        profiler = cProfile.Profile()
        try:
            return profiler.runcall(threading.Thread.run, self)
        finally:
            profiler.dump_stats('myprofile-%d.profile' % (self.ident,))

et utiliser cette classe ProfiledThread au lieu de la norme. Il pourrait vous donner plus de flexibilité, mais je ne suis pas sûr que ça vaut le coup, surtout si vous utilisez le code tiers qui ne serait pas utiliser votre classe.

Le python de wiki est une grande page pour les ressources de profilage: http://wiki.python.org/moin/PythonSpeed/PerformanceTips#Profiling_Code

tout comme le python docs: 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:

python -m cProfile -s time mine.py <args>

ou le fichier:

python -m cProfile -o output.file mine.py <args>

PS> Si vous utilisez Ubuntu, assurez-vous d'installer profil python

sudo apt-get install python-profiler 

Si vous sortie le fichier que vous pouvez obtenir de belles visualisations en utilisant les outils suivants

PyCallGraph: un outil pour créer des images appels graphique
  installation:

 sudo pip install pycallgraph

run:

 pycallgraph mine.py args

vue:

 gimp pycallgraph.png

Vous pouvez utiliser ce que vous voulez pour voir le fichier png, je gimp Malheureusement, je reçois souvent

point: graphique est trop grand pour bitmaps cairo-renderer. Mise à l'échelle par 0.257079 pour adapter

ce qui rend mes images unusably petites. Donc, je crée généralement des fichiers svg:

pycallgraph -f svg -o pycallgraph.svg mine.py <args>

PS> assurez-vous d'installer graphviz (qui fournit le programme de points):

sudo pip install graphviz

graphique alternatif utilisant gprof2dot via @maxy / @quodlibetor:

sudo pip install gprof2dot
python -m cProfile -o profile.pstats mine.py
gprof2dot -f pstats profile.pstats | dot -Tsvg -o mine.svg

@ commentaire de Maxy sur cette réponse m'a aidé assez que je pense qu'il mérite sa propre réponse: j'avais déjà cprofile fichiers -generated de .pstats et je ne voulais pas relancer les choses avec pycallgraph, donc j'utilisé gprof2dot , et a obtenu de jolis svgs:

$ sudo apt-get install graphviz
$ git clone https://github.com/jrfonseca/gprof2dot
$ ln -s "$PWD"/gprof2dot/gprof2dot.py ~/bin
$ cd $PROJECT_DIR
$ gprof2dot.py -f pstats profile.pstats | dot -Tsvg -o callgraph.svg

et Blam!

Il utilise le point (la même chose que pycallgraph utilise) si la sortie ressemble. J'ai l'impression que gprof2dot perd moins d'informations que:

exemple de sortie gprof2dot

Je suis tombé sur un outil pratique appelé SnakeViz lors de recherches sur ce sujet. SnakeViz est un outil de visualisation de profilage basé sur le Web. Il est très facile à installer et à utiliser. La manière habituelle, je l'utilise est de générer un fichier stat avec %prun puis faire une analyse en SnakeViz.

La principale technique de savoir utilisé est diagramme de rayon de soleil comme indiqué ci-dessous, dans laquelle la hiérarchie des appels de fonction est agencé en tant que couches d'arcs et les informations de temps codées dans leurs largeurs angulaires.

La meilleure chose est que vous pouvez interagir avec le tableau. Par exemple, pour zoomer on peut cliquer sur un arc, et l'arc et ses descendants seront agrandis en tant que nouveau sunburst pour afficher plus de détails.

enter image description ici

Je pense que cProfile est grand pour le profilage, tandis que kcachegrind est idéal pour visualiser les résultats. pyprof2calltree entre les poignées de la conversion de fichiers.

python -m cProfile -o script.profile script.py
pyprof2calltree -i script.profile -o script.calltree
kcachegrind script.calltree

Pour installer les outils nécessaires (sur Ubuntu, au moins):

apt-get install kcachegrind
pip install pyprof2calltree

Le résultat:

 Capture d'écran du résultat

Il faut aussi mentionner l'interface graphique cprofile spectateur vidage RunSnakeRun. Il vous permet de trier et de sélectionner, zoomer ainsi dans les parties pertinentes du programme. Les dimensions des rectangles de l'image est proportionnelle au temps nécessaire. 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 qui appelle la partie.

L'information descriptive est très utile. Il vous montre le code pour ce bit qui peut être utile lorsque vous traitez avec des appels de bibliothèque intégrés. Il vous indique quel fichier et de la ligne pour trouver le code.

tiens également à souligner à ce que l'OP a dit: « profilage », mais il semble qu'il voulait dire « timing ». Gardez à l'esprit des programmes d'fonctionnera plus lentement lorsque profilé.

entrer image description ici

Simplest et plus rapide façon de trouver où tout le temps va.

1. pip install snakeviz

2. python -m cProfile -o temp.dat <PROGRAM>.py

3. snakeviz temp.dat

Dessine un diagramme circulaire dans un navigateur. Le plus gros morceau est la fonction de problème. Très simple.

Un module de profilage agréable est le line_profiler (appelé à l'aide du kernprof.py script). Il peut être téléchargé .

Ma compréhension est que cprofile ne donne que des informations sur le temps total passé dans chaque fonction. Ainsi, les lignes individuelles de code ne sont pas chronométrées. Ceci est un problème dans le calcul scientifique car, souvent, une seule ligne peut prendre beaucoup de temps. En outre, comme je me souviens, cprofile n'a pas pris le temps que je passais à dire numpy.dot.

pProfile

line_profiler (déjà présenté ici) a également inspiré pprofile , qui est décrit comme suit:

  

Ligne granularité, fil courant déterministe et statistique pure python   profileur

Il fournit des lignes granularité comme line_profiler, est pur Python, peut être utilisé comme une commande autonome ou un module, et peut même générer des fichiers callgrind format qui peuvent être facilement analysés avec [k|q]cachegrind.

vprof

Il y a aussi vprof , un paquet Python décrit comme:

  

[...] fournissant visualisations riches et interactifs pour diverses caractéristiques du programme Python comme le temps en cours d'exécution et l'utilisation de la mémoire.

 heatmap

J'ai récemment créé thon pour visualiser les profils d'exécution et d'importation Python; cela peut être utile ici.

Installer avec

pip3 install tuna

Créer un profil d'exécution

python -mcProfile -o program.prof yourfile.py

ou un profil d'importation (obligatoire Python 3.7+)

python -X importprofile yourfile.py 2> import.log

Ensuite, il suffit d'exécuter le thon sur le fichier

tuna program.prof

Il y a beaucoup de bonnes réponses mais soit la ligne de commande d'utilisation ou d'un programme externe pour le profilage et / ou trier les résultats.

J'ai vraiment manqué d'une certaine façon je pourrais utiliser dans mon IDE (Eclipse-PyDev) sans toucher la ligne de commande ou d'installer quoi que ce soit. Alors voilà.

profilage sans ligne de commande

def count():
    from math import sqrt
    for x in range(10**5):
        sqrt(x)

if __name__ == '__main__':
    import cProfile, pstats
    cProfile.run("count()", "{}.profile".format(__file__))
    s = pstats.Stats("{}.profile".format(__file__))
    s.strip_dirs()
    s.sort_stats("time").print_stats(10)

Voir docs ou d'autres réponses pour plus d'informations.

Suite à la réponse de Joe Shaw sur le code multi-thread ne pas fonctionner comme prévu, je me suis dit que la méthode runcall dans cprofile fait simplement des appels self.enable() et self.disable() autour de l'appel de fonction profilée, de sorte que vous pouvez simplement faire vous-même et avoir tout ce que le code vous voulez en entre avec un minimum d'interférences avec le code existant.

Dans il y a une classe très utile et décorateur qui peut rendre le profilage (même pour les méthodes / fonctions spécifiques) très facile. La sortie peut alors être considérée très confortablement dans KCacheGrind.

cprofile est idéal pour le profilage rapide, mais la plupart du temps qu'il mettait fin pour moi les erreurs. Fonction runctx résout ce problème en initialisant correctement l'environnement et les variables, espérons qu'il peut être utile pour quelqu'un:

import cProfile
cProfile.runctx('foo()', None, locals())

Ma façon est d'utiliser Yappi ( https://code.google.com/p/yappi/ ) . Il est particulièrement utile combiné avec un serveur RPC où (même juste pour le débogage) vous méthode inscrivez pour démarrer, arrêter et imprimer des informations de profilage, par exemple de cette façon:

@staticmethod
def startProfiler():
    yappi.start()

@staticmethod
def stopProfiler():
    yappi.stop()

@staticmethod
def printProfiler():
    stats = yappi.get_stats(yappi.SORTTYPE_TTOT, yappi.SORTORDER_DESC, 20)
    statPrint = '\n'
    namesArr = [len(str(stat[0])) for stat in stats.func_stats]
    log.debug("namesArr %s", str(namesArr))
    maxNameLen = max(namesArr)
    log.debug("maxNameLen: %s", maxNameLen)

    for stat in stats.func_stats:
        nameAppendSpaces = [' ' for i in range(maxNameLen - len(stat[0]))]
        log.debug('nameAppendSpaces: %s', nameAppendSpaces)
        blankSpace = ''
        for space in nameAppendSpaces:
            blankSpace += space

        log.debug("adding spaces: %s", len(nameAppendSpaces))
        statPrint = statPrint + str(stat[0]) + blankSpace + " " + str(stat[1]).ljust(8) + "\t" + str(
            round(stat[2], 2)).ljust(8 - len(str(stat[2]))) + "\t" + str(round(stat[3], 2)) + "\n"

    log.log(1000, "\nname" + ''.ljust(maxNameLen - 4) + " ncall \tttot \ttsub")
    log.log(1000, statPrint)

Ensuite, lorsque votre travail de programme, vous pouvez commencer à profiler à tout moment en appelant la méthode RPC startProfiler et vider les informations de profilage dans un fichier journal en appelant printProfiler (ou modifier la méthode rpc pour le retourner à l'appelant) et obtenir une telle sortie:

2014-02-19 16:32:24,128-|SVR-MAIN  |-(Thread-3   )-Level 1000: 
name                                                                                                                                      ncall     ttot    tsub
2014-02-19 16:32:24,128-|SVR-MAIN  |-(Thread-3   )-Level 1000: 
C:\Python27\lib\sched.py.run:80                                                                                                           22        0.11    0.05
M:\02_documents\_repos\09_aheadRepos\apps\ahdModbusSrv\pyAheadRpcSrv\xmlRpc.py.iterFnc:293                                                22        0.11    0.0
M:\02_documents\_repos\09_aheadRepos\apps\ahdModbusSrv\serverMain.py.makeIteration:515                                                    22        0.11    0.0
M:\02_documents\_repos\09_aheadRepos\apps\ahdModbusSrv\pyAheadRpcSrv\PicklingXMLRPC.py._dispatch:66                                       1         0.0     0.0
C:\Python27\lib\BaseHTTPServer.py.date_time_string:464                                                                                    1         0.0     0.0
c:\users\zasiec~1\appdata\local\temp\easy_install-hwcsr1\psutil-1.1.2-py2.7-win32.egg.tmp\psutil\_psmswindows.py._get_raw_meminfo:243     4         0.0     0.0
C:\Python27\lib\SimpleXMLRPCServer.py.decode_request_content:537                                                                          1         0.0     0.0
c:\users\zasiec~1\appdata\local\temp\easy_install-hwcsr1\psutil-1.1.2-py2.7-win32.egg.tmp\psutil\_psmswindows.py.get_system_cpu_times:148 4         0.0     0.0
<string>.__new__:8                                                                                                                        220       0.0     0.0
C:\Python27\lib\socket.py.close:276                                                                                                       4         0.0     0.0
C:\Python27\lib\threading.py.__init__:558                                                                                                 1         0.0     0.0
<string>.__new__:8                                                                                                                        4         0.0     0.0
C:\Python27\lib\threading.py.notify:372                                                                                                   1         0.0     0.0
C:\Python27\lib\rfc822.py.getheader:285                                                                                                   4         0.0     0.0
C:\Python27\lib\BaseHTTPServer.py.handle_one_request:301                                                                                  1         0.0     0.0
C:\Python27\lib\xmlrpclib.py.end:816                                                                                                      3         0.0     0.0
C:\Python27\lib\SimpleXMLRPCServer.py.do_POST:467                                                                                         1         0.0     0.0
C:\Python27\lib\SimpleXMLRPCServer.py.is_rpc_path_valid:460                                                                               1         0.0     0.0
C:\Python27\lib\SocketServer.py.close_request:475                                                                                         1         0.0     0.0
c:\users\zasiec~1\appdata\local\temp\easy_install-hwcsr1\psutil-1.1.2-py2.7-win32.egg.tmp\psutil\__init__.py.cpu_times:1066               4         0.0     0.0 

Il ne peut pas être très utile pour les courts scripts mais permet d'optimiser les processus de type serveur en particulier compte tenu de la méthode printProfiler peut être appelé à plusieurs reprises au fil du temps à cerner et à comparer par exemple différents scénarios d'utilisation du programme.

  

Jamais eu envie de savoir ce que l'enfer que script python est en train de faire? Entrer le   Inspecter Shell. Shell inspectez vous permet d'imprimer / modifier et globals terme   fonctions sans interrompre le script en cours d'exécution. Maintenant avec   Auto-complétion et l'historique des commandes (uniquement sur linux).

     

Inspect Shell n'est pas un débogueur de style pdb.

https://github.com/amoffat/Inspect-Shell

Vous pouvez l'utiliser (et votre montre-bracelet).

Pour ajouter à https://stackoverflow.com/a/582337/1070617 ,

J'ai écrit ce module qui vous permet d'utiliser cprofile et de visualiser sa sortie facilement. Plus d'informations ici: https://github.com/ymichael/cprofilev

$ python -m cprofilev /your/python/program
# Go to http://localhost:4000 to view collected statistics.

Voir aussi: http://ymichael.com/ 2014/03/08 / profilage-python-avec-cprofile.html sur la façon de comprendre les statistiques collectées.

Un nouvel outil pour gérer le profilage dans le python est PyVmMonitor: http://www.pyvmmonitor.com/

Il a des caractéristiques uniques telles que

  • Joindre profileur à un programme en cours d'exécution (CPython)
  • Sur le profilage de la demande avec l'intégration Yappi
  • Profil sur une autre machine
  • processus multiples support (multitraitement, django ...)
  • vue échantillonnage direct / CPU (avec sélection de plage horaire)
  • profilage déterministes par l'intégration cprofile / profil
  • Analyser les résultats des pstats existants
  • Ouvrez les fichiers DOT
  • Accès API programatic
  • échantillons de groupe par la méthode ou la ligne
  • intégration PyDev
  • intégration PyCharm

Note:. Il est commercial, mais sans pour l'open source

Cela dépend de ce que vous voulez voir sur le profilage. temps simple les mesures peuvent être données par (bash).

time python python_prog.py

Même '/ usr / bin / time' peut produire des mesures détaillées en utilisant l'indicateur 'verbose'.

Pour vérifier les paramètres de temps donnés par chaque fonction et de mieux comprendre combien de temps est consacré à des fonctions, vous pouvez utiliser le cprofile intégré en python.

Entrant dans des mesures plus détaillées comme la performance, le temps est pas la seule mesure. Vous pouvez vous soucier de la mémoire, etc.
fils Options de profilage:
1. line_profiler est un autre profileur couramment utilisé pour trouver des mesures de synchronisation ligne par ligne.
2. memory_profiler est un outil pour le profil de la mémoire.
3. heapy (du projet Guppy) Profil comment les objets dans le tas sont utilisés.

Voici quelques-unes des plus courantes que je tends à utiliser. Mais si vous voulez en savoir plus, essayez de lire ce livre Il est un très bon livre sur commencer avec la performance à l'esprit. Vous pouvez déplacer sur des sujets avancés sur l'utilisation Cython et JIT (Just-in-time) python compilé.

Il y a aussi un profileur statistique appelée statprof . Il est un profileur d'échantillonnage, il ajoute une surcharge minimale à votre code et donne basé sur la ligne (pas seulement basés sur une fonction) timings. Il est plus adapté aux applications en temps réel comme les jeux mous, mais peut-être avoir moins de précision que cprofile.

Le la version en pypi est un peu vieux, donc peut l'installer avec pip par le dépôt git :

pip install git+git://github.com/bos/statprof.py@1a33eba91899afe17a8b752c6dfdec6f05dd0c01

Vous pouvez l'exécuter comme ceci:

import statprof

with statprof.profile():
    my_questionable_function()

Voir aussi https://stackoverflow.com/a/10333592/320036

Quand je ne suis pas root sur le serveur, j'utilise lsprofcalltree.py et exécuter mon programme comme celui-ci:

python lsprofcalltree.py -o callgrind.1 test.py

Ensuite, je peux ouvrir le rapport avec un logiciel compatible callgrind, comme qcachegrind

gprof2dot_magic

Fonction Magic gprof2dot à profil tout énoncé Python comme un graphique DOT dans Notebook JupyterLab ou Jupyter.

GitHub repo: https://github.com/mattijn/gprof2dot_magic

Installation

Assurez-vous que vous avez le paquet Python gprof2dot_magic.

pip install gprof2dot_magic

Ses dépendances gprof2dot et graphviz seront installés et

utilisation

Pour activer la fonction magique, d'abord charger le module gprof2dot_magic

%load_ext gprof2dot_magic

et le profil de toute déclaration de ligne sous forme de graphique DOT en tant que tel:

%gprof2dot print('hello world')

La solution terminale uniquement (et le plus simple) si tous ces UI de fantaisie de ne parviennent pas à installer ou à exécuter:
ignorer complètement cProfile et le remplacer par pyinstrument, qui va recueillir et afficher l'arborescence des appels juste après l'exécution.

Installer:

$ pip install pyinstrument

Profil et résultats Affichage:

$ python -m pyinstrument ./prog.py

Fonctionne avec python2 et 3.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top