python函数性能测试的简单介绍( 五 )


function_a() 0.001618 sec
function_b() 0.012786 sec
function_c() 0.003248 sec
在这一实例中,function_a()显然是最快的——至少对于这里使用的输入数据而言 。在有些情况下一一比如输入数据不同会对性能产生巨大影响——可能需要使用多组输入数据对每个函数进行测试,以便覆盖有代表性的测试用例,并对总执行时间或平均执行时间进行比较 。
有时监控自己的代码进行计时并不是很方便,因此timeit模块提供了一种在命令行中对代码执行时间进行计时的途径 。比如,要对MyModule.py模块中的函数function_a()进行计时,可以在控制台中输入如下命令:python3 -m timeit -n 1000 -s "from MyModule import function_a, X, Y" "function_a(X, Y)"(与通常所做的一样,对 Windows 环境 , 我们必须使用类似于C:Python3lpython.exe这样的内容来替换python3) 。-m选项用于Python 解释器 , 使其可以加载指定的模块(这里是timeit),其他选项则由timeit模块进行处理 。-n选项指定了循环计数次数,-s选项指定了要建立 , 最后一个参数是要执行和计时的代码 。命令完成后 , 会向控制台中打印运行结果 , 比如:
1000 loops, best of 3: 1.41 msec per loop
之后我们可以轻易地对其他两个函数进行计时,以便对其进行整体的比较 。
cProfile模块(或者profile模块,这里统称为cProfile模块)也可以用于比较函数 与方法的性能 。与只是提供原始计时的timeit模块不同的是,cProfile模块精确地展示 了有什么被调用以及每个调用耗费了多少时间 。下面是用于比较与前面一样的3个函数的代码:
if __name__ == "__main__":
for function in ("function_a", "function_b", "function_c"):
cProfile.run("for i in ranged 1000): {0}(X, Y)".format(function))
我们必须将重复的次数放置在要传递给cProfile.run()函数的代码内部,但不需要做任何创建,因为模块函数会使用内省来寻找需要使用的函数与变量 。这里没有使用显式的print()语句 , 因为默认情况下,cProfile.run()函数会在控制台中打印其输出 。下面给出的是所有函数的相关结果(有些无关行被省略,格式也进行了稍许调整,以便与页面适应):
1003 function calls in 1.661 CPU seconds
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.003 0.003 1.661 1.661:1 ( )
1000 1.658 0.002 1.658 0.002 MyModule.py:21 (function_a)
1 0.000 0.000 1.661 1.661 {built-in method exec}
5132003 function calls in 22.700 CPU seconds
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.487 0.487 22.700 22.700: 1 ( )
1000 0.011 0.000 22.213 0.022 MyModule.py:28(function_b)
5128000 7.048 0.000 7.048 0.000 MyModule.py:29( )
1000 0.00 50.000 0.005 0.000 {built-in method bisectjeft}
1 0.000 0.000 22.700 22.700 {built-in method exec}
1000 0.001 0.000 0.001 0.000 {built-in method len}
1000 15.149 0.015 22.196 0.022 {built-in method sorted}
5129003 function calls in 12.987 CPU seconds
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.205 0.205 12.987 12.987:l ( )
1000 6.472 0.006 12.782 0.013 MyModule.py:36(function_c)
5128000 6.311 0.000 6.311 0.000 MyModule.py:37( )
1 0.000 0.000 12.987 12.987 {built-in method exec}
ncalls ("调用的次数")列列出了对指定函数(在filename:lineno(function)中列出) 的调用次数 。回想一下我们重复了 1000次调用,因此必须将这个次数记住 。tottime (“总的时间”)列列出了某个函数中耗费的总时间,但是排除了函数调用的其他函数内部花费的时间 。第一个percall列列出了对函数的每次调用的平均时间(tottime // ncalls) 。cumtime ("累积时间")列出了在函数中耗费的时间,并且包含了函数调用的其他函数内部花费的时间 。第二个percall列列出了对函数的每次调用的平均时间,包括其调用的函数耗费的时间 。

推荐阅读