Le projet Euler et d'autres concours de codage ont souvent un temps maximal d'exécution ou les gens se vantent de la rapidité de leur solution particulière. Avec Python, les approches sont parfois un peu brutales - par exemple, en ajoutant du code de chronométrage à __main__
.
Quelle est la meilleure façon de déterminer la durée d'exécution d'un programme python ?
Python comprend un profileur appelé [cProfile][1]. Il ne se contente pas de donner le temps d'exécution total, mais chronomètre également 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 :
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 rendre les choses encore plus faciles, j'ai créé un petit fichier batch appelé 'profile.bat' :
python -m cProfile %1
Donc tout ce que j'ai à faire est de le lancer :
profile euler048.py
Et j'obtiens 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 : Mise à jour du lien vers une bonne ressource vidéo de PyCon 2013 intitulée. Python Profiling [Également via YouTube](
[1] : https://docs.python.org/3/library/profile.html#module-cProfile
Il convient de souligner que l'utilisation du profileur ne fonctionne (par défaut) que sur le thread principal, et que vous n'obtiendrez aucune information des autres threads si vous les utilisez. Cela peut être une sorte de piège, car cela n'est pas mentionné dans la [documentation du profileur][1].
Si vous souhaitez également profiler les threads, vous pouvez consulter la fonction [threading.setprofile()
][2] dans la documentation.
Vous pouvez également 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 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.
[1] : http://docs.python.org/library/profile.html [2] : http://docs.python.org/library/threading.html#threading.setprofile "fonction threading.setprofile()" ;
Dans [source][1] de Virtaal, il y a 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. Le résultat peut ensuite être visualisé de manière très confortable dans KCacheGrind.
[1] : https://github.com/translate/virtaal/blob/master/devsupport/profiling.py