62 votes

Chronométrage précis des fonctions en python

Je suis à la programmation en python sur windows et souhaitez mesurer avec précision le temps qu'il faut pour une fonction à exécuter. J'ai écrit une fonction "time_it" qui prend une autre fonction, l'exécute et renvoie le temps qu'il a fallu pour exécuter.

def time_it(f, *args):
    start = time.clock()
    f(*args)
    return (time.clock() - start)*1000

j'appelle cela 1000 fois et la moyenne du résultat. (les 1000 constante à la fin est de donner la réponse en millisecondes.)

Cette fonction semble fonctionner mais j'ai ce sentiment tenace que je suis en train de faire quelque chose de mal, et qu'en le faisant de cette façon, je suis en utilisant plus de temps que la fonction utilise lors de son exécution.

Est-il plus standard ou accepté pour ce faire?

Quand j'ai changé mon test de la fonction à appeler un imprimer de sorte qu'il dure plus longtemps, mon time_it fonction retourne une moyenne de 2,5 ms tandis que le cProfile.run('f()') retourne et la moyenne de 7.0 ms. J'ai pensé que ma fonction serait surestimer le temps si quoi que ce soit, ce qui se passe ici?

Une remarque supplémentaire, c'est le temps relatif de fonctions par rapport à l'autre que je me soucie, pas le temps absolu comme ce sera évidemment varier selon le matériel et d'autres facteurs.

69voto

Alex Martelli Points 330805

Utilisez le module timeit de la bibliothèque standard Python.

Utilisation de base:

 from timeit import Timer

# first argument is the code to be run, the second "setup" argument is only run once,
# and it not included in the execution time.
t = Timer("""x.index(123)""", setup="""x = range(1000)""")

print t.timeit() # prints float, for example 5.8254
# ..or..
print t.timeit(1000) # repeat 1000 times instead of the default 1million
 

37voto

Daniel Lew Points 39063

Au lieu d'écrire votre propre code de profilage, je vous suggère de consulter les profileurs Python intégrés ( profile ou cProfile , selon vos besoins): http: //docs.python. org / bibliothèque / profil.html

30voto

vdrmrt Points 464

Vous pouvez créer un décorateur "timeme" comme

 import time                                                

def timeme(method):
    def wrapper(*args, **kw):
        startTime = int(round(time.time() * 1000))
        result = method(*args, **kw)
        endTime = int(round(time.time() * 1000))

        print(endTime - startTime,'ms')
        return result

    return wrapper

@timeme
def func1(a,b,c = 'c',sleep = 1):
    time.sleep(sleep)
    print(a,b,c)

func1('a','b','c',0)
func1('a','b','c',0.5)
func1('a','b','c',0.6)
func1('a','b','c',1)
 

23voto

S.Lott Points 207588

Ce code est très imprécis

total= 0
for i in range(1000):
    start= time.clock()
    function()
    end= time.clock()
    total += end-start
time= total/1000

Ce code est moins inexactes

start= time.clock()
for i in range(1000):
    function()
end= time.clock()
time= (end-start)/1000

La très imprécis souffre d'un biais de mesure si le moment de l'exécution de la fonction est proche de l'exactitude de l'horloge. La plupart du temps mesurés sont simplement des nombres aléatoires entre 0 et quelques tops de l'horloge.

En fonction de votre charge de travail du système, le "temps" vous observer à partir d'une seule fonction peut être tout à fait un artefact de l'OS de la planification et d'autres incontrôlable frais généraux.

La deuxième version (moins inexacte) a moins d'un biais de mesure. Si votre fonction est vraiment rapide, vous devrez peut-être exécuter à 10 000 fois à l'humidité, hors de l'OS de la planification et d'autres frais généraux.

Les deux sont, bien sûr, terriblement trompeuse. Le temps d'exécution de votre programme, dans son ensemble, n'est pas la somme de la fonction d'exécution de fois. Vous ne pouvez utiliser les numéros relative des comparaisons. Ils ne sont pas des mesures absolues qui véhiculent beaucoup de sens.

14voto

antitrust Points 4853

Si vous voulez le temps d'un python méthode, même si vous bloquer mesure pourrait lancer, une bonne approche est d'utiliser with déclaration. Définir quelques - Timer classe

import time

class Timer:    
    def __enter__(self):
        self.start = time.clock()
        return self

    def __exit__(self, *args):
        self.end = time.clock()
        self.interval = self.end - self.start

Ensuite, vous pouvez de temps un mode de connexion qui peut jeter. Utilisation

import httplib

with Timer() as t:
    conn = httplib.HTTPConnection('google.com')
    conn.request('GET', '/')

print('Request took %.03f sec.' % t.interval)

__exit()__ méthode sera appelée, même si la demande de connexion thows. Plus précisément, vous aurez vous utilisez try finally pour voir le résultat dans le cas où il jette, comme avec

try:
    with Timer() as t:
        conn = httplib.HTTPConnection('google.com')
        conn.request('GET', '/')
finally:
    print('Request took %.03f sec.' % t.interval)

Plus de détails ici.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X