python函数性能 python代码( 六 )


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列列出了对函数的每次调用的平均时间,包括其调用的函数耗费的时间 。
这种输出信息要比timeit模块的原始计时信息富有启发意义的多 。我们立即可以发现,function_b()与function_c()使用了被调用5000次以上的生成器 , 使得它们的速度至少要比function_a()慢10倍以上 。并且,function_b()调用了更多通常意义上的函数 , 包括调用内置的sorted()函数,这使得其几乎比function_c()还要慢两倍 。当然,timeit() 模块提供了足够的信息来查看计时上存在的这些差别,但cProfile模块允许我们了解为什么会存在这些差别 。正如timeit模块允许对代码进行计时而又不需要对其监控一样,cProfile模块也可以做到这一点 。然而,从命令行使用cProfile模块时,我们不能精确地指定要执行的 是什么——而只是执行给定的程序或模块 , 并报告所有这些的计时结果 。需要使用的 命令行是python3 -m cProfile programOrModule.py,产生的输出信息与前面看到的一 样,下面给出的是输出信息样例,格式上进行了一些调整,并忽略了大多数行:
10272458 function calls (10272457 primitive calls) in 37.718 CPU secs
ncalls tottime percall cumtime percall filename:lineno(function)
10.000 0.000 37.718 37.718:1 ( )
10.719 0.719 37.717 37.717:12( )
1000 1.569 0.002 1.569 0.002:20(function_a)
1000 0.011 0.000 22.560 0.023:27(function_b)
5128000 7.078 0.000 7.078 0.000:28( )
1000 6.510 0.007 12.825 0.013:35(function_c)
5128000 6.316 0.000 6.316 0.000:36( )
在cProfile术语学中,原始调用指的就是非递归的函数调用 。
以这种方式使用cProfile模块对于识别值得进一步研究的区域是有用的 。比如,这里 我们可以清晰地看到function_b()需要耗费更长的时间 , 但是我们怎样获取进一步的详细资料?我们可以使用cProfile.run("function_b()")来替换对function_b()的调用 。或者可以保存完全的profile数据并使用pstats模块对其进行分析 。要保存profile,就必须对命令行进行稍许修改:python3 -m cProfile -o profileDataFile programOrModule.py 。之后可以对 profile 数据进行分析,比如启动IDLE,导入pstats模块,赋予其已保存的profileDataFile,或者也可以在控制台中交互式地使用pstats 。

推荐阅读