Точное время выполнения функций в python
я программирую на python в windows и хотел бы точно измерить время, необходимое для запуска функции. Я написал функцию "time_it", которая принимает другую функцию, запускает ее и возвращает время, необходимое для запуска.
def time_it(f, *args):
start = time.clock()
f(*args)
return (time.clock() - start)*1000
Я называю это 1000 раз и средний результат. (константа 1000 в конце должна дать ответ в миллисекундах.)
эта функция, кажется, работает, но у меня такое неприятное чувство, что я делаю что-то неправильно, и что делая это таким образом, я использую больше времени, чем функция на самом деле использует для его работы.
есть ли более стандартный или принятый способ сделать это?
когда я изменил свою тестовую функцию для вызова печати, чтобы она занимала больше времени, моя функция time_it возвращает в среднем 2,5 мс, а cProfile.доходы('Ф()') и среднем 7.0 МС. Я понял, что моя функция будет переоценивать время, если что-нибудь, что здесь происходит?
еще одно примечание, это относительное время функций по сравнению друг с другом, о котором я забочусь, а не абсолютное время, поскольку это, очевидно, зависит от аппаратного обеспечения и других факторов.
7 ответов:
вместо того, чтобы писать свой собственный код профилирования, я предлагаю вам проверить встроенные профилировщики 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()__
метод будет вызван, даже если запрос соединения thows. Точнее, вы бы использовалиtry
finally
чтобы увидеть результат в случае, если он бросает, а сtry: with Timer() as t: conn = httplib.HTTPConnection('google.com') conn.request('GET', '/') finally: print('Request took %.03f sec.' % t.interval)