Project Euler和其他编码竞赛通常有最长的运行时间,或者人们吹嘘他们的特定解决方案运行速度有多快。对于Python,有时方法有些笨拙——即向__main__添加计时代码。
描述Python程序运行时间的好方法是什么?
Project Euler和其他编码竞赛通常有最长的运行时间,或者人们吹嘘他们的特定解决方案运行速度有多快。对于Python,有时方法有些笨拙——即向__main__添加计时代码。
描述Python程序运行时间的好方法是什么?
当前回答
我发现cprofiler和其他资源更多地用于优化目的,而不是调试。
我制作了自己的测试模块,用于简单的python脚本速度测试。(在我的例子中,使用ScriptProfilerPy测试了1K+行py文件,并在几分钟内将代码速度提高了10倍。
模块ScriptProfilerPy()将运行代码,并向其添加时间戳。我把模块放在这里:https://github.com/Lucas-BLP/ScriptProfilerPy
Use:
from speed_testpy import ScriptProfilerPy
ScriptProfilerPy("path_to_your_script_to_test.py").Profiler()
输出:
其他回答
cProfile非常适合于分析,而kcachegrind非常适合于可视化结果。中间的pyprov2calltree处理文件转换。
python -m cProfile -o script.profile script.py
pyprof2calltree -i script.profile -o script.calltree
kcachegrind script.calltree
所需的系统包:
kcachegrind(Linux)、qcachegrind(MacOs)
Ubuntu上的设置:
apt-get install kcachegrind
pip install pyprof2calltree
结果:
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
如果你想做一个累积分析器,意思是连续运行函数几次并观察结果的总和。
您可以使用此cumulative_profiler装饰器:
它是python>=3.6特定的,但您可以删除非本地的,因为它可以在旧版本上工作。
import cProfile, pstats
class _ProfileFunc:
def __init__(self, func, sort_stats_by):
self.func = func
self.profile_runs = []
self.sort_stats_by = sort_stats_by
def __call__(self, *args, **kwargs):
pr = cProfile.Profile()
pr.enable() # this is the profiling section
retval = self.func(*args, **kwargs)
pr.disable()
self.profile_runs.append(pr)
ps = pstats.Stats(*self.profile_runs).sort_stats(self.sort_stats_by)
return retval, ps
def cumulative_profiler(amount_of_times, sort_stats_by='time'):
def real_decorator(function):
def wrapper(*args, **kwargs):
nonlocal function, amount_of_times, sort_stats_by # for python 2.x remove this row
profiled_func = _ProfileFunc(function, sort_stats_by)
for i in range(amount_of_times):
retval, ps = profiled_func(*args, **kwargs)
ps.print_stats()
return retval # returns the results of the function
return wrapper
if callable(amount_of_times): # incase you don't want to specify the amount of times
func = amount_of_times # amount_of_times is the function in here
amount_of_times = 5 # the default amount
return real_decorator(func)
return real_decorator
实例
剖析函数baz
import time
@cumulative_profiler
def baz():
time.sleep(1)
time.sleep(2)
return 1
baz()
baz跑了5次并打印了以下内容:
20 function calls in 15.003 seconds
Ordered by: internal time
ncalls tottime percall cumtime percall filename:lineno(function)
10 15.003 1.500 15.003 1.500 {built-in method time.sleep}
5 0.000 0.000 15.003 3.001 <ipython-input-9-c89afe010372>:3(baz)
5 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
指定次数
@cumulative_profiler(3)
def baz():
...
找到所有时间去向的最简单快捷的方法。
1. pip install snakeviz
2. python -m cProfile -o temp.dat <PROGRAM>.py
3. snakeviz temp.dat
在浏览器中绘制饼图。最大的部分是问题函数。非常简单。
获取IPython笔记本上的快速配置文件统计信息。人们可以将line_profiler和memory_profile直接嵌入到笔记本中。
另一个有用的包是Pympler。它是一个强大的评测包,能够跟踪类、对象、函数、内存泄漏等。
了解了!
!pip install line_profiler
!pip install memory_profiler
!pip install pympler
加载它!
%load_ext line_profiler
%load_ext memory_profiler
使用它!
%时间
%time print('Outputs CPU time,Wall Clock time')
#CPU times: user 2 µs, sys: 0 ns, total: 2 µs Wall time: 5.96 µs
给予:
CPU时间:CPU级执行时间systimes:系统级执行时间总计:CPU时间+系统时间墙上时间:墙上时钟时间
%计时
%timeit -r 7 -n 1000 print('Outputs execution time of the snippet')
#1000 loops, best of 7: 7.46 ns per loop
给出给定循环次数(n)中的最佳运行次数(r)。输出系统缓存的详细信息:当代码片段被多次执行时,系统会缓存一些操作并不再执行,这可能会影响概要文件报告的准确性。
%普鲁士人
%prun -s cumulative 'Code to profile'
给予:
函数调用数(ncall)每个函数调用有个条目(不同)每次呼叫所用时间(百分比)到函数调用为止的时间(cumtime)调用的函数/模块的名称等。。。
%记忆,记忆
%memit 'Code to profile'
#peak memory: 199.45 MiB, increment: 0.00 MiB
给予:
内存使用情况
%低压运行
#Example function
def fun():
for i in range(10):
print(i)
#Usage: %lprun <name_of_the_function> function
%lprun -f fun fun()
给予:
按行统计
系统大小
sys.getsizeof('code to profile')
# 64 bytes
返回对象的大小(以字节为单位)。
来自pympler的asizeof()
from pympler import asizeof
obj = [1,2,("hey","ha"),3]
print(asizeof.asizeof(obj,stats=4))
pympler.asizeof可用于调查某些Python对象消耗多少内存。与sys.getsizeof不同,asizeof递归地调整对象大小
来自pympler的跟踪器
from pympler import tracker
tr = tracker.SummaryTracker()
def fun():
li = [1,2,3]
di = {"ha":"haha","duh":"Umm"}
fun()
tr.print_diff()
跟踪函数的生存期。
Pympler包包含大量用于评测代码的高实用函数。这里无法涵盖所有这些。有关详细的概要文件实现,请参阅随附的文档。
Pympler文档