Project Euler和其他编码竞赛经常有一个最大运行时间,或者人们吹嘘他们的特定解决方案的运行速度。 对于Python,有时方法有些笨拙--即在__main__
中加入计时代码。
有什么好的方法可以剖析一个python程序的运行时间?
Python 包含一个叫做 cProfile 的分析器。它不仅给出了总的运行时间,还对每个函数分别进行了计时,并告诉你每个函数被调用了多少次,这样就很容易确定你应该在哪里进行优化。
你可以从你的代码中,或者从解释器中调用它,就像这样。
import cProfile
cProfile.run('foo()')
更有用的是,你可以在运行脚本时调用cProfile。
python -m cProfile myscript.py
为了更方便,我做了一个小批处理文件,叫做'profile.bat'。
python -m cProfile %1
所以我所要做的就是运行。
profile euler048.py
然后我就得到了这个。
1007 function calls in 0.061 CPU seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 0.061 0.061 <string>:1(<module>)
1000 0.051 0.000 0.051 0.000 euler048.py:2(<lambda>)
1 0.005 0.005 0.061 0.061 euler048.py:2(<module>)
1 0.000 0.000 0.061 0.061 {execfile}
1 0.002 0.002 0.053 0.053 {map}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler objects}
1 0.000 0.000 0.000 0.000 {range}
1 0.003 0.003 0.003 0.003 {sum}
EDIT: 更新了PyCon 2013的一个好的视频资源链接,标题为 Python Profiling [也通过YouTube](
值得指出的是,使用剖析器只在主线程上工作(默认情况下),如果你使用其他线程,你不会得到任何信息。 这可能是一个小问题,因为在剖析器文档中完全没有提到它。
如果你也想对线程进行剖析,你会想看看文档中的threading.setprofile()
函数。
你也可以创建你自己的threading.Thread
子类来做这件事。
class ProfiledThread(threading.Thread):
# Overrides threading.Thread.run()
def run(self):
profiler = cProfile.Profile()
try:
return profiler.runcall(threading.Thread.run, self)
finally:
profiler.dump_stats('myprofile-%d.profile' % (self.ident,))
并使用那个ProfiledThread
类来代替标准的。 这可能会给你带来更多的灵活性,但我不确定这是否值得,特别是如果你使用的是第三方代码,不会使用你的类。