我开始用来cProfile描述我的python脚本.我注意到一些非常奇怪的事情.
当我time用来测量脚本的运行时间时需要4.3秒.
当我使用python -m cProfile script.py它需要7.3秒.
在代码中运行探查器时:
import profile
profile.run('main()')
Run Code Online (Sandbox Code Playgroud)
需要63秒!!
我可以理解为什么加分析时,它可能需要更多一点时间,但为什么会出现使用之间的这种差异cProfile来自外部或代码的一部分?我使用这么多时间有原因profile.run吗?
奇怪的是,你所看到的是预期的行为.在Python文档的概要分析部分的介绍中,它指出profile与...相比,增加了"分析程序的显着开销" cProfile.你看到的差异在于你正在使用的库,而不是你如何调用它们.考虑这个脚本:
import profile
import cProfile
def nothing():
return
def main():
for i in xrange(1000):
for j in xrange(1000):
nothing()
return
cProfile.run('main()')
profile.run('main()')
Run Code Online (Sandbox Code Playgroud)
cProfile显示main 的输出大约需要0.143秒才能运行,而profile变量则报告1.645秒,大约是11.5倍.
现在让我们再次将脚本更改为:
def nothing():
return
def main():
for i in xrange(1000):
for j in xrange(1000):
nothing()
return
if __name__ == "__main__":
main()
Run Code Online (Sandbox Code Playgroud)
并使用分析器调用它:
python -m profile test_script.py
报告主要运行1.662秒.
python -m cProfile test_script.py
报告主要运行0.143秒.
这说明你启动剖析的方式无关,与你之间看到的差异cProfile和profile.差异是由两个分析器如何处理"事件"(如函数调用或返回)引起的.在这两种情况下,执行代码中都有软件挂钩,触发回调以跟踪这些事件,并执行更新事件计数器以及启动或停止计时器等操作.但是,该profile模块本身在Python中处理所有这些事件,这意味着您的解释器必须保留您的代码,执行回调内容,然后返回继续您的代码.
同样的事情必须发生cProfile(执行分析回调),但它更快,因为回调用C语言编写.看看两个模块文件profile.py和cProfile.py演示了一些差异:
Profile类profile.py不从任何其他类(线111)继承,而Profile在类cProfile.py(线66)继承_lsprof.Profiler,这是C源文件中实现.正如文档所述,cProfile通常是要走的路,因为它主要是用C实现的,所以一切都更快.
另外,您可以profile通过校准来提高性能.文档中提供了有关如何执行此操作的详细信息有关如何/为何所有这些内容的更多详细信息,请参阅有关确定性分析和限制的Python文档部分.
cProfile更快,因为顾名思义,它的大部分是用C实现的.这与profile模块形成对比,模块必须处理本机Python中的所有分析回调.无论是从命令行调用分析器还是在脚本中手动调用,都不会影响两个模块之间的时差.