Ecco le mie scoperte dopo aver esaminato molte buone risposte qui e alcuni altri articoli.
Innanzitutto, se stai discutendo tra timeit
etime.time
, timeit
hanno due vantaggi:
timeit
seleziona il miglior timer disponibile sul tuo sistema operativo e sulla versione di Python.
timeit
disabilita la garbage collection, tuttavia, questo non è qualcosa che potresti o non potresti desiderare.
Ora il problema è che timeit
non è così semplice da usare perché ha bisogno di installazione e le cose si fanno brutte quando hai un sacco di importazioni. Idealmente, vuoi solo un decoratore o usarewith
blocco e misurare il tempo. Sfortunatamente, non è disponibile nulla per questo, quindi hai due opzioni:
Opzione 1: utilizzare la libreria timebudget
Il timebudget è una libreria versatile e molto semplice che puoi usare solo in una riga di codice dopo l'installazione pip.
@timebudget # Record how long this function takes
def my_method():
# my code
Opzione 2: utilizzare direttamente il modulo di codice
Ho creato sotto un piccolo modulo di utilità.
# utils.py
from functools import wraps
import gc
import timeit
def MeasureTime(f, no_print=False, disable_gc=False):
@wraps(f)
def _wrapper(*args, **kwargs):
gcold = gc.isenabled()
if disable_gc:
gc.disable()
start_time = timeit.default_timer()
try:
result = f(*args, **kwargs)
finally:
elapsed = timeit.default_timer() - start_time
if disable_gc and gcold:
gc.enable()
if not no_print:
print('"{}": {}s'.format(f.__name__, elapsed))
return result
return _wrapper
class MeasureBlockTime:
def __init__(self,name="(block)", no_print=False, disable_gc=False):
self.name = name
self.no_print = no_print
self.disable_gc = disable_gc
def __enter__(self):
self.gcold = gc.isenabled()
if self.disable_gc:
gc.disable()
self.start_time = timeit.default_timer()
def __exit__(self,ty,val,tb):
self.elapsed = timeit.default_timer() - self.start_time
if self.disable_gc and self.gcold:
gc.enable()
if not self.no_print:
print('Function "{}": {}s'.format(self.name, self.elapsed))
return False #re-raise any exceptions
Ora puoi cronometrare qualsiasi funzione semplicemente posizionandoti davanti un decoratore:
import utils
@utils.MeasureTime
def MyBigFunc():
#do something time consuming
for i in range(10000):
print(i)
Se vuoi cronometrare parte del codice, basta inserirlo nel with
blocco:
import utils
#somewhere in my code
with utils.MeasureBlockTime("MyBlock"):
#do something time consuming
for i in range(10000):
print(i)
# rest of my code
vantaggi:
Esistono diverse versioni con il mezzo supporto fluttuanti, quindi desidero sottolineare alcuni punti salienti:
- Utilizzare il timer da timeit anziché time.time per i motivi descritti in precedenza.
- Se lo desideri, puoi disabilitare GC durante il cronometraggio.
- Decorator accetta funzioni con parametri con o senza nome.
- Possibilità di disabilitare la stampa nei tempi di blocco (usare
with utils.MeasureBlockTime() as t
e quindi t.elapsed
).
- Possibilità di mantenere abilitato gc per i tempi di blocco.