Habituellement, j'utilise la commande Shell time
. Mon but est de tester si les données sont petites, moyennes, grandes ou très grandes, combien de temps et d'utilisation de la mémoire seront.
Des outils pour Linux ou juste python pour ce faire?
Jetez un œil à timeit , le python et pycallgraph .
def test():
"""Stupid test function"""
lst = []
for i in range(100):
lst.append(i)
if __== '__main__':
import timeit
print(timeit.timeit("test()", setup="from __main__ import test"))
Essentiellement, vous pouvez le passer python en tant que paramètre de chaîne, et il s'exécutera dans le nombre de fois spécifié et affichera le temps d'exécution. Les bits importants des documents:
timeit.timeit(stmt='pass', setup='pass', timer=<default timer>, number=1000000)
Créez une instance
Timer
avec l'instruction donnée, setup code et timer fonction et exécutez sa méthodetimeit
avec nombre exécutions.
... et:
Timer.timeit(number=1000000)
Heure nombre exécutions de l'instruction principale. Cela exécute l'instruction de configuration une fois, puis retourne le temps nécessaire pour exécuter l'instruction principale un certain nombre de fois, mesuré en secondes sous forme de flottant. L'argument est le nombre de fois dans la boucle, par défaut à un million. L'instruction principale, l'instruction d'installation et la fonction de temporisation à utiliser sont transmises au constructeur.
Remarque
Par défaut,
timeit
désactive temporairementgarbage collection
Pendant le chronométrage. L'avantage de cette approche est qu'elle rend les timings indépendants plus comparables. Cet inconvénient est que le GC peut être un élément important des performances de la fonction mesurée. Si c'est le cas, GC peut être réactivé comme première instruction de la chaîne setup. Par exemple:
timeit.Timer('for i in xrange(10): oct(i)', 'gc.enable()').timeit()
Le profilage vous donnera une beaucoup idée plus détaillée de ce qui se passe. Voici "l'exemple instantané" de les documents officiels :
import cProfile
import re
cProfile.run('re.compile("foo|bar")')
Ce qui vous donnera:
197 function calls (192 primitive calls) in 0.002 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 0.001 0.001 <string>:1(<module>)
1 0.000 0.000 0.001 0.001 re.py:212(compile)
1 0.000 0.000 0.001 0.001 re.py:268(_compile)
1 0.000 0.000 0.000 0.000 sre_compile.py:172(_compile_charset)
1 0.000 0.000 0.000 0.000 sre_compile.py:201(_optimize_charset)
4 0.000 0.000 0.000 0.000 sre_compile.py:25(_identityfunction)
3/1 0.000 0.000 0.000 0.000 sre_compile.py:33(_compile)
Ces deux modules devraient vous donner une idée de l'endroit où rechercher les goulots d'étranglement.
Aussi, pour vous familiariser avec la sortie de profile
, jetez un œil à ce post
Ce module utilise graphviz pour créer des callgraphs comme celui-ci:
Vous pouvez facilement voir les chemins les plus utilisés par couleur. Vous pouvez soit les créer à l'aide de l'API pycallgraph, soit à l'aide d'un script packagé:
pycallgraph graphviz -- ./mypythonscript.py
Les frais généraux sont cependant assez considérables. Ainsi, pour les processus déjà longs, la création du graphique peut prendre un certain temps.
J'utilise un simple décorateur pour chronométrer le func
def st_time(func):
"""
st decorator to calculate the total time of a func
"""
def st_func(*args, **keyArgs):
t1 = time.time()
r = func(*args, **keyArgs)
t2 = time.time()
print "Function=%s, Time=%s" % (func.__name__, t2 - t1)
return r
return st_func
Le module timeit
était lent et bizarre, alors j'ai écrit ceci:
def timereps(reps, func):
from time import time
start = time()
for i in range(0, reps):
func()
end = time()
return (end - start) / reps
Exemple:
import os
listdir_time = timereps(10000, lambda: os.listdir('/'))
print "python can do %d os.listdir('/') per second" % (1 / listdir_time)
Pour moi, ça dit:
python can do 40925 os.listdir('/') per second
Il s'agit d'une sorte primitive de benchmarking, mais c'est assez bon.
Je fais habituellement un rapide time ./script.py
pour voir combien de temps cela prend. Cela ne vous montre cependant pas la mémoire, du moins pas par défaut. Vous pouvez utiliser /usr/bin/time -v ./script.py
pour obtenir beaucoup d'informations, y compris l'utilisation de la mémoire.
Memory Profiler pour tous vos besoins en mémoire.
https://pypi.python.org/pypi/memory_profiler
Exécutez une installation pip:
pip install memory_profiler
Importez la bibliothèque:
import memory_profiler
Ajoutez un décorateur à l'article que vous souhaitez profiler:
@profile
def my_func():
a = [1] * (10 ** 6)
b = [2] * (2 * 10 ** 7)
del b
return a
if __== '__main__':
my_func()
Exécutez le code:
python -m memory_profiler example.py
Recevoir la sortie:
Line # Mem usage Increment Line Contents
==============================================
3 @profile
4 5.97 MB 0.00 MB def my_func():
5 13.61 MB 7.64 MB a = [1] * (10 ** 6)
6 166.20 MB 152.59 MB b = [2] * (2 * 10 ** 7)
7 13.61 MB -152.59 MB del b
8 13.61 MB 0.00 MB return a
Les exemples proviennent des documents, liés ci-dessus.
Jetez un œil à nez et à l'un de ses plugins, celui-ci en particulier.
Une fois installé, nose est un script sur votre chemin, et que vous pouvez appeler dans un répertoire contenant quelques scripts python:
$: nosetests
Cela va chercher dans tous les fichiers python dans le répertoire courant et exécutera toute fonction qu'il reconnaît comme test: par exemple, il reconnaît toute fonction avec le mot test_ dans son nom comme test .
Vous pouvez donc simplement créer un script python appelé test_yourfunction.py et y écrire quelque chose comme ceci:
$: cat > test_yourfunction.py
def test_smallinput():
yourfunction(smallinput)
def test_mediuminput():
yourfunction(mediuminput)
def test_largeinput():
yourfunction(largeinput)
Ensuite, vous devez exécuter
$: nosetest --with-profile --profile-stats-file yourstatsprofile.prof testyourfunction.py
et pour lire le fichier de profil, utilisez cette ligne python:
python -c "import hotshot.stats ; stats = hotshot.stats.load('yourstatsprofile.prof') ; stats.sort_stats('time', 'calls') ; stats.print_stats(200)"
Attention timeit
est très lent, il faut 12 secondes sur mon processeur moyen pour simplement l'initialiser (ou peut-être exécuter la fonction). vous pouvez tester cette réponse acceptée
def test():
lst = []
for i in range(100):
lst.append(i)
if __== '__main__':
import timeit
print(timeit.timeit("test()", setup="from __main__ import test")) # 12 second
pour une chose simple, j'utiliserai time
à la place, sur mon PC, il retournera le résultat 0.0
import time
def test():
lst = []
for i in range(100):
lst.append(i)
t1 = time.time()
test()
result = time.time() - t1
print(result) # 0.000000xxxx
Le moyen facile de tester rapidement n'importe quelle fonction est d'utiliser cette syntaxe: %timeit my_code
Par exemple :
%timeit a = 1
13.4 ns ± 0.781 ns per loop (mean ± std. dev. of 7 runs, 100000000 loops each)