Project Euler和其他编码竞赛通常有最长的运行时间,或者人们吹嘘他们的特定解决方案运行速度有多快。对于Python,有时方法有些笨拙——即向__main__添加计时代码。
描述Python程序运行时间的好方法是什么?
Project Euler和其他编码竞赛通常有最长的运行时间,或者人们吹嘘他们的特定解决方案运行速度有多快。对于Python,有时方法有些笨拙——即向__main__添加计时代码。
描述Python程序运行时间的好方法是什么?
当前回答
python wiki是一个用于分析资源的绝佳页面:http://wiki.python.org/moin/PythonSpeed/PerformanceTips#Profiling_Code
python文档也是如此:http://docs.python.org/library/profile.html
如Chris Lawlor所示,cProfile是一个很棒的工具,可以很容易地打印到屏幕上:
python -m cProfile -s time mine.py <args>
或存档:
python -m cProfile -o output.file mine.py <args>
PS>如果您使用的是Ubuntu,请确保安装python配置文件
apt-get install python-profiler
如果输出到文件,可以使用以下工具获得良好的可视化效果
PyCallGraph:创建调用图图像的工具安装:
pip install pycallgraph
run:
pycallgraph mine.py args
视图:
gimp pycallgraph.png
你可以使用任何你喜欢的方式来查看png文件,我使用了gimp不幸的是,我经常
dot:graph对于cairo渲染器位图太大。缩放0.257079以适合
这使我的图像变得难以使用。所以我通常创建svg文件:
pycallgraph -f svg -o pycallgraph.svg mine.py <args>
PS>确保安装graphviz(提供点程序):
pip install graphviz
使用gprof2dot通过@maxy/@quodlibetor绘制替代图形:
pip install gprof2dot
python -m cProfile -o profile.pstats mine.py
gprof2dot -f pstats profile.pstats | dot -Tsvg -o mine.svg
其他回答
我发现,如果您不想使用命令行选项,该功能快速且易于使用。
要使用,只需在要分析的每个函数上方添加@profile。
def profile(fnc):
"""
Profiles any function in following class just by adding @profile above function
"""
import cProfile, pstats, io
def inner (*args, **kwargs):
pr = cProfile.Profile()
pr.enable()
retval = fnc (*args, **kwargs)
pr.disable()
s = io.StringIO()
sortby = 'cumulative' #Ordered
ps = pstats.Stats(pr,stream=s).strip_dirs().sort_stats(sortby)
n=10 #reduced the list to be monitored
ps.print_stats(n)
#ps.dump_stats("profile.prof")
print(s.getvalue())
return retval
return inner
每个函数的输出如下
Ordered by: cumulative time
List reduced from 38 to 10 due to restriction <10>
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 0.002 0.002 3151212474.py:37(get_pdf_page_count)
1 0.000 0.000 0.002 0.002 fitz.py:3604(__init__)
1 0.001 0.001 0.001 0.001 {built-in method fitz._fitz.new_Document}
1 0.000 0.000 0.000 0.000 fitz.py:5207(__del__)
1 0.000 0.000 0.000 0.000 {built-in method fitz._fitz.delete_Document}
1 0.000 0.000 0.000 0.000 fitz.py:4816(init_doc)
1 0.000 0.000 0.000 0.000 fitz.py:5197(_reset_page_refs)
1 0.000 0.000 0.000 0.000 fitz.py:4821(<listcomp>)
11 0.000 0.000 0.000 0.000 fitz.py:4054(_getMetadata)
1 0.000 0.000 0.000 0.000 weakref.py:241(values)
我刚刚从pypref_time中开发了自己的分析器:
https://github.com/modaresimr/auto_profiler
更新版本2
安装:
pip install auto_profiler
快速入门:
from auto_profiler import Profiler
with Profiler():
your_function()
在Jupyter中使用,可以实时查看已用时间
更新版本1
通过添加装饰器,它将显示一个耗时的函数树
@探查器(深度=4)
Install by: pip install auto_profiler
实例
import time # line number 1
import random
from auto_profiler import Profiler, Tree
def f1():
mysleep(.6+random.random())
def mysleep(t):
time.sleep(t)
def fact(i):
f1()
if(i==1):
return 1
return i*fact(i-1)
def main():
for i in range(5):
f1()
fact(3)
with Profiler(depth=4):
main()
示例输出
Time [Hits * PerHit] Function name [Called from] [function location]
-----------------------------------------------------------------------
8.974s [1 * 8.974] main [auto-profiler/profiler.py:267] [/test/t2.py:30]
├── 5.954s [5 * 1.191] f1 [/test/t2.py:34] [/test/t2.py:14]
│ └── 5.954s [5 * 1.191] mysleep [/test/t2.py:15] [/test/t2.py:17]
│ └── 5.954s [5 * 1.191] <time.sleep>
|
|
| # The rest is for the example recursive function call fact
└── 3.020s [1 * 3.020] fact [/test/t2.py:36] [/test/t2.py:20]
├── 0.849s [1 * 0.849] f1 [/test/t2.py:21] [/test/t2.py:14]
│ └── 0.849s [1 * 0.849] mysleep [/test/t2.py:15] [/test/t2.py:17]
│ └── 0.849s [1 * 0.849] <time.sleep>
└── 2.171s [1 * 2.171] fact [/test/t2.py:24] [/test/t2.py:20]
├── 1.552s [1 * 1.552] f1 [/test/t2.py:21] [/test/t2.py:14]
│ └── 1.552s [1 * 1.552] mysleep [/test/t2.py:15] [/test/t2.py:17]
└── 0.619s [1 * 0.619] fact [/test/t2.py:24] [/test/t2.py:20]
└── 0.619s [1 * 0.619] f1 [/test/t2.py:21] [/test/t2.py:14]
这取决于您希望从分析中看到什么。简单的时间度量可以由(bash)给出。
time python python_prog.py
甚至“/usr/bin/time”也可以使用“--verbose”标志输出详细的度量。
为了检查每个函数给出的时间度量,并更好地了解在函数上花费的时间,可以使用python中的内置cProfile。
进入更详细的指标,如绩效,时间不是唯一的指标。您可以担心内存、线程等问题。分析选项:line_profiler是另一个通常用于逐行查找定时度量的分析器。2.memory_profiler是一个评测内存使用情况的工具。3.heapy(来自项目Guppy)描述如何使用堆中的对象。
这些是我常用的一些。但如果你想了解更多,试试看这本书这是一本非常好的书,讲述了如何从性能出发。您可以转到使用Cython和JIT(实时)编译的python的高级主题。
在Virtaal的源代码中,有一个非常有用的类和装饰器,它可以使分析(甚至对于特定的方法/函数)非常简单。然后可以在KCacheGrind中非常舒适地查看输出。
PyVmMonitor是一种在Python中处理评测的新工具:http://www.pyvmmonitor.com/
它具有一些独特的功能,例如
将探查器附加到正在运行的(CPython)程序Yappi集成的按需分析不同机器上的配置文件多进程支持(多处理、django…)实时采样/CPU视图(带时间范围选择)通过cProfile/配置文件集成进行确定性配置分析现有PStats结果打开DOT文件编程API访问按方法或行对样本进行分组PyDev集成PyCharm集成
注意:它是商业的,但对开源是免费的。