Accurate timing of functions in python
我正在Windows上用python编程,希望准确地测量函数运行所需的时间。我编写了一个函数"timeu it",它接受另一个函数,运行它,并返回运行它所花费的时间。
1 2 3 4 | def time_it(f, *args): start = time.clock() f(*args) return (time.clock() - start)*1000 |
我称之为1000次,平均结果。(结尾的1000个常量以毫秒为单位给出答案。)
这个函数似乎可以工作,但是我有一种烦躁的感觉,我在做一些错误的事情,通过这样做,我使用的时间比函数运行时实际使用的时间要多。
有没有一种更为标准或公认的方法来做到这一点?
当我将测试函数更改为调用打印以便花费更长时间时,我的时间函数返回平均2.5 ms,而cprofile.run("f()")返回平均7.0 ms。我认为我的函数会高估时间,如果有什么情况,这里会发生什么?
另一个注意事项是,我关心的是函数之间的相对时间,而不是绝对时间,因为这明显取决于硬件和其他因素。
型
使用python标准库中的
基本用途:
1 2 3 4 5 6 7 8 9 | 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 |
型
我建议您检查内置的python profiler(
型
你可以这样做一个"TimeMe"装饰器
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | 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) |
。
型
这个代码非常不准确
1 2 3 4 5 6 7 | total= 0 for i in range(1000): start= time.clock() function() end= time.clock() total += end-start time= total/1000 |
号
这个代码不太准确
1 2 3 4 5 | start= time.clock() for i in range(1000): function() end= time.clock() time= (end-start)/1000 |
如果函数的运行时间接近时钟的精度,那么非常不准确的函数会受到测量偏差的影响。大多数被测量的时间只是时钟0到几滴答之间的随机数。
根据系统工作负载的不同,从单个函数观察到的"时间"可能完全是操作系统调度和其他不可控制开销的产物。
第二个版本(不太准确)的测量偏差较小。如果您的函数真的很快,您可能需要运行它10000次,以减少操作系统调度和其他开销。
当然,这两种方法都具有严重的误导性。程序的运行时间(作为一个整体)不是函数运行时间的总和。您只能使用这些数字进行相对比较。它们不是绝对的度量标准,没有多大意义。
型
如果您想给python方法计时,即使您度量的块可能抛出,一个好的方法是使用
1 2 3 4 5 6 7 8 9 10 | 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 |
。
然后,您可能需要对可能抛出的连接方法进行计时。使用
1 2 3 4 5 6 7 | import httplib with Timer() as t: conn = httplib.HTTPConnection('google.com') conn.request('GET', '/') print('Request took %.03f sec.' % t.interval) |
即使连接请求失败,也将调用
1 2 3 4 5 6 | try: with Timer() as t: conn = httplib.HTTPConnection('google.com') conn.request('GET', '/') finally: print('Request took %.03f sec.' % t.interval) |
。
更多详细信息。
型
这个比较干净
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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的答案
1 2 | import timeit timeit.timeit(fun, number=10000) |
。
能做到这一点。