Python Language Profilage de code


Exemple

Tout d'abord, vous devriez être capable de trouver le goulot d'étranglement de votre script et noter qu'aucune optimisation ne peut compenser un mauvais choix dans la structure des données ou une faille dans la conception de votre algorithme. Deuxièmement, n'essayez pas d'optimiser trop tôt votre processus de codage au détriment de la lisibilité / conception / qualité. Donald Knuth a fait la déclaration suivante sur l'optimisation:

"Nous devrions oublier les petites efficacités, disons environ 97% du temps: l'optimisation prématurée est la racine de tous les maux. Pourtant, nous ne devrions pas laisser passer nos opportunités dans ces 3% critiques"

Pour profiler votre code, vous disposez de plusieurs outils: cProfile (ou le profile plus lent) de la bibliothèque standard, line_profiler et timeit . Chacun d'eux sert un but différent.

cProfile est un profileur déterministe: l'appel de fonction, le retour de fonction et les événements d'exception sont surveillés, et des temporisations précises sont établies pour les intervalles entre ces événements (jusqu'à 0,001s). La documentation de la bibliothèque ([ https://docs.python.org/2/library/profile.html][1]) nous fournit un cas d'utilisation simple

import cProfile
def f(x):
    return "42!"
cProfile.run('f(12)')

Ou si vous préférez envelopper des parties de votre code existant:

import cProfile, pstats, StringIO
pr = cProfile.Profile()
pr.enable()
# ... do something ...
# ... long ...
pr.disable()
sortby = 'cumulative'
ps = pstats.Stats(pr, stream=s).sort_stats(sortby)
ps.print_stats()
print s.getvalue()

Cela créera des sorties ressemblant au tableau ci-dessous, où vous pourrez voir rapidement où votre programme passe le plus de temps et identifier les fonctions à optimiser.

         3 function calls in 0.000 seconds

Ordered by: standard name
ncalls  tottime  percall  cumtime  percall filename:lineno(function)
     1    0.000    0.000    0.000    0.000 <stdin>:1(f)
     1    0.000    0.000    0.000    0.000 <string>:1(<module>)
     1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}

Le module line_profiler ([ https://github.com/rkern/line_profiler]]) est utile pour avoir une analyse ligne par ligne de votre code. Ceci n'est évidemment pas gérable pour les scripts longs mais vise les extraits de code. Voir la documentation pour plus de détails. La manière la plus simple de commencer est d'utiliser le script kernprof comme expliqué sur la page du package, notez que vous devrez spécifier manuellement la ou les fonctions à profiler.

$ kernprof -l script_to_profile.py

kernprof va créer une instance de LineProfiler et l'insérer dans l'espace de noms __builtins__ avec le profil name. Il a été écrit pour être utilisé comme décorateur, donc dans votre script, vous décorez les fonctions que vous souhaitez profiler avec @profile .

@profile
def slow_function(a, b, c):
    ...

Le comportement par défaut de kernprof consiste à placer les résultats dans un fichier binaire script_to_profile.py.lprof . Vous pouvez dire à kernprof d'afficher immédiatement les résultats formatés au terminal avec l'option [-v / - view]. Sinon, vous pouvez voir les résultats plus tard comme ceci:

$ python -m line_profiler script_to_profile.py.lprof

Finalement, timeit fournit un moyen simple de tester une ligne ou une petite expression à la fois à partir de la ligne de commande et du shell python. Ce module répondra à une question telle que, est-il plus rapide de faire une liste ou d'utiliser la list() intégrée list() lors de la transformation d'un ensemble en liste. Recherchez le mot-clé setup ou l'option -s pour ajouter le code d'installation.

>>> import timeit
>>> timeit.timeit('"-".join(str(n) for n in range(100))', number=10000)
0.8187260627746582

d'un terminal

$ python -m timeit '"-".join(str(n) for n in range(100))'
10000 loops, best of 3: 40.3 usec per loop