Точная синхронизация функций в python

Я программирую в python на окнах и хочу точно измерить время, необходимое для запуска функции. Я написал функцию «time_it», которая выполняет другую функцию, запускает ее и возвращает время, затраченное на выполнение.

def time_it(f, *args): start = time.clock() f(*args) return (time.clock() - start)*1000 

я называю это 1000 раз и усредняет результат. (константа 1000 в конце – дать ответ в миллисекундах).

Эта функция, похоже, работает, но я чувствую, что я делаю что-то неправильно, и что, делая это таким образом, я использую больше времени, чем функция, фактически используемая при ее запуске.

Есть ли более стандартный или приемлемый способ сделать это?

Когда я изменил свою тестовую функцию, чтобы вызвать печать, чтобы она заняла больше времени, моя функция time_it возвращает среднее значение в 2,5 мс, тогда как cProfile.run ('f ()') возвращается и в среднем составляет 7,0 мс. Я полагал, что моя функция будет переоценивать время, если что-нибудь, что здесь происходит?

Еще одно примечание: это относительное время функций по сравнению друг с другом, о котором я забочусь, а не о абсолютном времени, поскольку это, очевидно, будет меняться в зависимости от аппаратного обеспечения и других факторов.

7 Solutions collect form web for “Точная синхронизация функций в python”

Вместо написания собственного кода профилирования я предлагаю вам проверить встроенные профилиры Python ( profile или cProfile , в зависимости от ваших потребностей): http://docs.python.org/library/profile.html

Используйте модуль timeit из стандартной библиотеки Python.

Основное использование:

 from timeit import Timer # first argument is the code to be run, the second "setup" argument is only run once, # and it not included in the execution time. t = Timer("""x.index(123)""", setup="""x = range(1000)""") print t.timeit() # prints float, for example 5.8254 # ..or.. print t.timeit(1000) # repeat 1000 times instead of the default 1million 

Вы можете создать декоратор «timeme», например

 import time def timeme(method): def wrapper(*args, **kw): startTime = int(round(time.time() * 1000)) result = method(*args, **kw) endTime = int(round(time.time() * 1000)) print(endTime - startTime,'ms') return result return wrapper @timeme def func1(a,b,c = 'c',sleep = 1): time.sleep(sleep) print(a,b,c) func1('a','b','c',0) func1('a','b','c',0.5) func1('a','b','c',0.6) func1('a','b','c',1) 

Этот код очень неточный

 total= 0 for i in range(1000): start= time.clock() function() end= time.clock() total += end-start time= total/1000 

Этот код менее неточный

 start= time.clock() for i in range(1000): function() end= time.clock() time= (end-start)/1000 

Очень неточно страдает от смещения измерения, если время выполнения функции близко к точности часов. Большинство измеренных времен – это просто случайные числа от 0 до нескольких тиков часов.

В зависимости от рабочей нагрузки вашей системы «время», которое вы наблюдаете от одной функции, может быть полностью артефактом планирования ОС и другими неконтролируемыми накладными расходами.

Вторая версия (менее неточная) имеет меньшую погрешность измерения. Если ваша функция очень быстрая, вам может потребоваться запустить ее 10 000 раз, чтобы отключить планирование ОС и другие накладные расходы.

Оба они, конечно, ужасно вводят в заблуждение. Время выполнения вашей программы – в целом – не является суммой времени выполнения функции. Вы можете использовать только цифры для относительных сравнений. Они не являются абсолютными измерениями, которые придают большое значение.

Если вы хотите использовать метод python, даже если блокировка, которую вы измеряете, может бросить, один хороший подход – использовать with оператором. Определите некоторый класс Timer как

 import time class Timer: def __enter__(self): self.start = time.clock() return self def __exit__(self, *args): self.end = time.clock() self.interval = self.end - self.start 

Затем вы можете захотеть использовать метод соединения, который может быть брошен. использование

 import httplib with Timer() as t: conn = httplib.HTTPConnection('google.com') conn.request('GET', '/') print('Request took %.03f sec.' % t.interval) 

__exit()__ будет вызываться, даже если запрашивается запрос на соединение. Точнее, вы бы использовали try finally увидеть результат в случае его броска, как в случае с

 try: with Timer() as t: conn = httplib.HTTPConnection('google.com') conn.request('GET', '/') finally: print('Request took %.03f sec.' % t.interval) 

Подробнее здесь.

Это опрятно

 from contextlib import contextmanager import time @contextmanager def timeblock(label): start = time.clock() try: yield finally: end = time.clock() print ('{} : {}'.format(label, end - start)) with timeblock("just a test"): print "yippee" 

Подобно ответу @ AlexMartelli

 import timeit timeit.timeit(fun, number=10000) 

может сделать трюк.

  • Pytest: Как проверить функцию с помощью входного вызова?
  • Как правильно выполнить тестовую изоляцию с помощью модуля Python с состоянием?
  • Утепление Python: запуск тестов в другом модуле
  • Как проверить сеанс в ресурсе фляжки
  • Как обрабатывать несколько утверждений в рамках одного элемента управления Python?
  • Выполнение модульных тестов по вложенным функциям
  • Наследование теста носа на основе Python: приборы для тестирования нагрузочных единиц из подклассов
  • Python - проверить исключение свойств
  • Python - лучший язык программирования в мире.