Oto moje ustalenia po przejściu wielu dobrych odpowiedzi tutaj, a także kilku innych artykułów.
Po pierwsze, jeśli debatujesz między timeit
i time.time
, timeit
ma dwie zalety:
timeit
wybiera najlepszy czasomierz dostępny w wersji systemu operacyjnego i Pythona.
timeit
wyłącza zbieranie śmieci, jednak nie jest to coś, czego możesz chcieć lub nie.
Problem polega na tym, że timeit
nie jest tak prosty w użyciu, ponieważ wymaga konfiguracji, a rzeczy stają się brzydkie, gdy masz wiele importów. Idealnie potrzebujesz po prostu dekoratora lub użyj with
bloku i zmierz czas. Niestety, nie ma w tym nic wbudowanego, więc masz dwie opcje:
Opcja 1: Użyj biblioteki timebudget
Timebudget jest wszechstronnym i bardzo prosty biblioteki, który można wykorzystać tylko w jednym wierszu kodu po pip zainstalować.
@timebudget # Record how long this function takes
def my_method():
# my code
Opcja 2: użyj modułu kodu bezpośrednio
Stworzyłem poniżej mały moduł narzędziowy.
# 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
Teraz możesz ustawić czas dowolnej funkcji, umieszczając przed nią dekorator:
import utils
@utils.MeasureTime
def MyBigFunc():
#do something time consuming
for i in range(10000):
print(i)
Jeśli chcesz odmierzyć fragment kodu, po prostu włóż go do with
bloku:
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
Zalety:
Krąży kilka wersji z półprawą, więc chcę wskazać kilka najważniejszych:
- Używaj timera od timeit zamiast time.time z powodów opisanych wcześniej.
- Możesz wyłączyć GC podczas pomiaru czasu, jeśli chcesz.
- Dekorator akceptuje funkcje z nazwanymi lub nienazwanymi parametrami.
- Możliwość wyłączenia drukowania w czasie blokowania (użyj,
with utils.MeasureBlockTime() as t
a następnie t.elapsed
).
- Możliwość utrzymania włączonej gc dla taktowania bloku.