Вот мои выводы, пройдя здесь много хороших ответов, а также несколько других статей.
Во-первых, если вы спорите между timeit
и time.time
, у timeit
него есть два преимущества:
timeit
выбирает лучший таймер, доступный в вашей версии ОС и Python.
timeit
отключает сборку мусора, однако это не то, что вы можете или не можете хотеть.
Теперь проблема в том, что timeit
это не так просто использовать, потому что он требует настройки, и все становится ужасно, когда у вас есть куча импорта. В идеале, вы просто хотите декоратор или использоватьwith
блок и измерять время. К сожалению, для этого нет ничего встроенного, поэтому у вас есть два варианта:
Вариант 1. Использование библиотеки временных бюджетов
Timebudget является универсальной и очень простой библиотекой, которую можно использовать только в одной строке коды после установки пипа.
@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 включенным для синхронизации блока.