web-dev-qa-db-fra.com

mesurer avec précision le temps python prend

J'ai besoin de mesurer le temps que prennent certaines parties de mon programme (pas pour le débogage mais comme fonctionnalité dans la sortie). La précision est importante car le temps total sera d'une fraction de seconde.

J'allais utiliser le module de temps quand je suis tombé sur timeit , qui prétend éviter un certain nombre de pièges courants pour mesurer les temps d'exécution . Malheureusement, il a une interface horrible, prenant une chaîne en entrée qu'il évalue ensuite.

Alors, dois-je utiliser ce module pour mesurer le temps avec précision, ou le temps suffira-t-il? Et quels sont les pièges auxquels il fait référence?

Merci

42
hoju

Selon le Python documentation , cela a à voir avec la précision de la fonction de temps dans différents systèmes d'exploitation:

La fonction de minuterie par défaut dépend de la plate-forme. Sous Windows, time.clock () a une granularité en microsecondes, mais la granularité de time.time () est de 1/60e de seconde; sous Unix, time.clock () a une granularité au 1/100ème de seconde et time.time () est beaucoup plus précis. Sur les deux plates-formes, les fonctions de minuterie par défaut mesurent l'heure de l'horloge murale, et non l'heure du processeur. Cela signifie que d'autres processus s'exécutant sur le même ordinateur peuvent interférer avec le timing ... Sur Unix, vous pouvez utiliser time.clock () pour mesurer le temps CPU.

Pour extraire directement du code de timeit.py:

if sys.platform == "win32":
    # On Windows, the best timer is time.clock()
    default_timer = time.clock
else:
    # On most other platforms the best timer is time.time()
    default_timer = time.time

En outre, il traite directement de la configuration du code d'exécution pour vous. Si vous utilisez time, vous devez le faire vous-même. Ceci, bien sûr vous fait gagner du temps

Configuration de Timeit:

def inner(_it, _timer):
    #Your setup code
    %(setup)s
    _t0 = _timer()
    for _i in _it:
        #The code you want to time
        %(stmt)s
    _t1 = _timer()
    return _t1 - _t0

Python 3:

Depuis Python 3.3 vous pouvez utiliser time.perf_counter() (synchronisation à l'échelle du système) ou time.process_time() (synchronisation à l'échelle du processus), exactement comme vous utilisiez time.clock():

from time import process_time

t = process_time()
#do some stuff
elapsed_time = process_time() - t

La nouvelle fonction process_time N'inclura pas le temps écoulé pendant le sommeil.

Python 3.7+:

Depuis Python 3.7, vous pouvez également utiliser process_time_ns() qui est similaire à process_time() mais renvoie le temps en nanosecondes.

30
Sean Vieira

Vous pouvez créer un contexte de synchronisation (voir PEP 34 ) pour mesurer assez facilement des blocs de code.

from __future__ import with_statement
import time

class Timer(object):
    def __enter__(self):
        self.__start = time.time()

    def __exit__(self, type, value, traceback):
        # Error handling here
        self.__finish = time.time()

    def duration_in_seconds(self):
        return self.__finish - self.__start

timer = Timer()

with timer:
    # Whatever you want to measure goes here
    time.sleep(2)

print timer.duration_in_seconds()    
28
Corey Porter

Le module timeit semble avoir été conçu pour effectuer des tests de performances d'algorithmes, plutôt que comme une simple surveillance d'une application. Votre meilleure option est probablement d'utiliser le module de temps, d'appeler time.time() au début et à la fin du segment qui vous intéresse et de soustraire les deux nombres. Sachez que le nombre que vous obtenez peut avoir beaucoup plus de décimales que la résolution réelle de la minuterie système.

8
qid

Avez-vous examiné le profil de fonctionnalité ou le profil c fourni?

http://docs.python.org/library/profile.html

Cela fournit des informations beaucoup plus détaillées que la simple impression de l'heure avant et après un appel de fonction. Ça vaut peut-être le coup d'oeil ...

4
AJ.

J'ai été ennuyé aussi par l'interface horrible de timeit donc j'ai fait une bibliothèque pour cela, vérifiez-la, c'est trivial à utiliser


from pythonbenchmark import compare, measure
import time

a,b,c,d,e = 10,10,10,10,10
something = [a,b,c,d,e]

def myFunction(something):
    time.sleep(0.4)

def myOptimizedFunction(something):
    time.sleep(0.2)

# comparing test
compare(myFunction, myOptimizedFunction, 10, input)
# without input
compare(myFunction, myOptimizedFunction, 100)

https://github.com/Karlheinzniebuhr/pythonbenchmark

4
karlpy

La documentation mentionne également que time.clock () et time.time () ont une résolution différente selon la plate-forme. Sous Unix, time.clock () mesure le temps processeur par opposition à l'heure de l'horloge murale.

timeit désactive également la récupération de place lors de l'exécution des tests, ce qui n'est probablement pas ce que vous voulez pour le code de production.

Je trouve que time.time () suffit dans la plupart des cas.

2
Chris AtLee

De Python 2.6 à l'heure, il n'est plus limité à la chaîne d'entrée. Citer la documentation :

Modifié dans la version 2.6: Les paramètres stmt et setup peuvent désormais également prendre des objets qui peuvent être appelés sans arguments. Cela va les incorporer dans une fonction de temporisation qui sera ensuite exécutée par timeit (). Notez que le temps système est un peu plus important dans ce cas en raison des appels de fonction supplémentaires.

2
jgosmann