Ось мої висновки після перегляду багатьох хороших відповідей, а також кількох інших статей.
По-перше, якщо ви дискутуєте між timeit
і time.time
, timeit
має два переваги:
timeit
вибирає найкращий таймер, доступний для вашої ОС та версії Python.
timeit
вимикає збирання сміття, однак, це не те, що ви можете або не хочете.
Тепер проблема полягає в тому, що timeit
це не так просто у використанні, оскільки він потребує налаштування, і все стає некрасивим, коли у вас є маса імпорту. В ідеалі ви просто хочете декоратор або використовуватиwith
блок і вимірюєте час. На жаль, для цього немає нічого вбудованого, тому у вас є два варіанти:
Варіант 1: Використовуйте бібліотеку часових бюджетів
Бюджет часу - це універсальна і дуже проста бібліотека, яку ви можете використовувати лише в одному рядку коду після установки pip.
@timebudget # Record how long this function takes
def my_method():
# my code
Варіант 2: Використовуйте модуль коду безпосередньо
Я створив нижче невеликий модуль корисності.
# 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
Тепер ви можете виконати будь-яку функцію, просто поставивши декоратор перед нею:
import utils
@utils.MeasureTime
def MyBigFunc():
#do something time consuming
for i in range(10000):
print(i)
Якщо ви хочете затримати частину коду, тоді просто покладіть його всередину with
блоку:
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
Переваги:
Існує кілька напівзахисних версій, що плавають навколо, тому я хочу зазначити кілька важливих моментів:
- Використовуйте таймер від timeit замість time.time з причин, описаних раніше.
- Ви можете відключити GC під час синхронізації.
- Декоратор приймає функції з іменованими або безіменними парамами.
- Можливість відключення друку в блок-часі (користування
with utils.MeasureBlockTime() as t
та потім t.elapsed
).
- Можливість утримувати gc увімкнено для блокування хронометражу.