如何使用Pythons timeit计算代码段以测试性能?

Mes*_*ika 140 python testing timeit database-tuning

我有一个python脚本,它应该正常工作,但我需要编写执行时间.我用谷歌搜索了我应该使用timeit但我似乎无法让它工作.

我的Python脚本如下所示:

import sys
import getopt
import timeit
import random
import os
import re
import ibm_db
import time
from string import maketrans
myfile = open("results_update.txt", "a")

for r in range(100):
    rannumber = random.randint(0, 100)

    update = "update TABLE set val = %i where MyCount >= '2010' and MyCount < '2012' and number = '250'" % rannumber
    #print rannumber

    conn = ibm_db.pconnect("dsn=myDB","usrname","secretPWD")

for r in range(5):
    print "Run %s\n" % r        
    ibm_db.execute(query_stmt)
 query_stmt = ibm_db.prepare(conn, update)

myfile.close()
ibm_db.close(conn)
Run Code Online (Sandbox Code Playgroud)

我需要的是执行查询并将其写入文件所需的时间results_update.txt.目的是使用不同的索引和调整机制测试我的数据库的更新语句.

joa*_*uin 238

您可以使用time.time()time.clock()想要时间的块之前和之后.

import time

t0 = time.time()
code_block
t1 = time.time()

total = t1-t0
Run Code Online (Sandbox Code Playgroud)

这种方法不像timeit(它不是平均几次运行)那样精确,但它很简单.

time.time()(在Windows和Linux中)和time.clock()(在Linux中)对于快速功能来说不够精确(总计= 0).在这种情况下,或者如果您要平均几运行所经过的时间,你必须手动调用函数多次(如我想你在你的示例代码已经在做和timeit自动做当设置数量参数)

import time

def myfast():
   code

n = 10000
t0 = time.time()
for i in range(n): myfast()
t1 = time.time()

total_n = t1-t0
Run Code Online (Sandbox Code Playgroud)

在Windows中,正如Corey在评论中所说的那样,time.clock()具有更高的精度(微秒而不是秒),并且优先于time.time().

  • 更新:time.clock()现已弃用.您现在应该使用time.time().实际上,从版本3.3开始,最好的选择是time.perf_counter() (13认同)
  • 您可以使用timeit.default_timer()使您的代码平台独立; 它返回适合OS的time.clock()或time.time(). (10认同)
  • 在Windows上使用fyi,使用time.clock()而不是time.time() (8认同)
  • 而不是手动选择时钟,使用[`timeit.default_timer`](https://docs.python.org/2/library/timeit.html#timeit.default_timer); Python已经为你完成了这项工作.但实际上,你应该使用`timeit.timeit(myfast,number = n)`而不是重新发明重复的调用轮(并且错过了`timeit`在重复运行代码时禁用垃圾收集器的事实). (6认同)
  • 谢谢科里,为什么?因为时钟更精确(微秒)还是还有更多东西? (4认同)
  • @joaquin 你能在答案中添加 `time.perf_counter()` 作为 Python 3 中更好的替代方案吗?当系统更改时间或发生闰秒时,它不会出现异常行为,并且始终具有可用的最佳精度(除了使用“perf_counter_ns()”来避免浮点不准确)。 (3认同)
  • 我认为值得一提的是`time.time()`以秒为单位输出时间,作为浮点数. (2认同)
  • 就其价值而言, timeit 取的是重复运行的最短时间而不是平均值。 (2认同)

mun*_*unk 39

如果您正在分析您的代码并且可以使用IPython,它具有神奇的功能%timeit.

%%timeit 在细胞上运作.

In [2]: %timeit cos(3.14)
10000000 loops, best of 3: 160 ns per loop

In [3]: %%timeit
   ...: cos(3.14)
   ...: x = 2 + 3
   ...: 
10000000 loops, best of 3: 196 ns per loop
Run Code Online (Sandbox Code Playgroud)


Ale*_*lli 33

从时序且不说,这个代码告诉你简直是不正确的:你执行100个连接(完全无视所有,但最后一个),然后当你要做的第一执行调用你传递一个局部变量query_stmt,你只初始化的执行呼叫.

首先,使您的代码正确,而不必担心时间安排:即一个函数,它建立或接收连接并在该连接上执行100或500或任何数量的更新,然后关闭连接.一旦你的代码正常工作,就可以考虑使用timeit它了!

具体来说,如果你想要的时间函数是一个无参数的函数你foobar可以使用timeit.timeit(2.6或更高版本 - 它在2.5及之前更复杂):

timeit.timeit('foobar()', number=1000)
Run Code Online (Sandbox Code Playgroud)

您最好指定运行次数,因为默认情况下,一百万,可能对您的用例来说很高(导致在此代码中花费大量时间;-).

  • 在为最后几分钟努力奋斗之后,我想让未来的观众知道如果你的函数`foobar`在主文件中,你也可能想要传递一个设置变量.像这样:`timeit.timeit('foobar()','from __main__ import foobar',number = 1000)` (24认同)
  • 在Python 2.7.8中,您可以简单地使用`timeit.timeit(foobar,number = 1000)` (3认同)

inf*_*nge 9

这是史蒂文答案的简单包装。此函数不会重复运行/求平均值,只是让您不必到处重复计时代码:)

'''function which prints the wall time it takes to execute the given command'''
def time_func(func, *args): #*args can take 0 or more 
  import time
  start_time = time.time()
  func(*args)
  end_time = time.time()
  print("it took this long to run: {}".format(end_time-start_time))
Run Code Online (Sandbox Code Playgroud)


Mar*_*ers 8

专注于一个特定的事情.磁盘I/O很慢,所以如果您要调整的是数据库查询,我会把它从测试中拿出来.

如果您需要计算数据库执行时间,请查找数据库工具,例如询问查询计划,并注意性能不仅取决于确切的查询和您拥有的索引,还取决于数据加载(数据量)你已经存储了).

也就是说,您可以简单地将代码放在函数中并运行该函数timeit.timeit():

def function_to_repeat():
    # ...

duration = timeit.timeit(function_to_repeat, number=1000)
Run Code Online (Sandbox Code Playgroud)

这将禁用垃圾收集,重复调用该function_to_repeat()函数,并使用这些调用的总持续时间timeit.default_timer(),这是您特定平台的最准确可用时钟.

您应该将设置代码移出重复的功能; 例如,您应首先连接到数据库,然后仅查询查询.使用setup参数导入或创建这些依赖项,并将它们传递给您的函数:

def function_to_repeat(var1, var2):
    # ...

duration = timeit.timeit(
    'function_to_repeat(var1, var2)',
    'from __main__ import function_to_repeat, var1, var2', 
    number=1000)
Run Code Online (Sandbox Code Playgroud)

会抓住全局变量function_to_repeat,var1var2从你的脚本中将每个重复传递给函数.


Eld*_*uid 5

如何使用以下方法对函数进行计时timeit

import timeit

def time_this():
    return 'a' + 'b'

timeit.timeit(time_this, number=1000)
Run Code Online (Sandbox Code Playgroud)

time_this()它返回运行1000 次所花费的时间(以秒为单位) 。