Project Euler和其他编码竞赛通常有最长的运行时间,或者人们吹嘘他们的特定解决方案运行速度有多快。对于Python,有时方法有些笨拙——即向__main__添加计时代码。
描述Python程序运行时间的好方法是什么?
Project Euler和其他编码竞赛通常有最长的运行时间,或者人们吹嘘他们的特定解决方案运行速度有多快。对于Python,有时方法有些笨拙——即向__main__添加计时代码。
描述Python程序运行时间的好方法是什么?
当前回答
我刚刚从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的高级主题。
gprof2dot_magic公司
gprof2dot的神奇函数,用于在JupyterLab或Jupyter Notebook中将任何Python语句作为DOT图进行评测。
GitHub回购:https://github.com/mattijn/gprof2dot_magic
安装
确保您有Python包gprof2dot_magic。
pip install gprof2dot_magic
它的依赖关系gprof2dot和graphviz也将被安装
用法
要启用magic函数,首先加载gprof2dot_magic模块
%load_ext gprof2dot_magic
然后将任何行语句配置为DOT图,如下所示:
%gprof2dot print('hello world')
@Maxy对这个答案的评论对我帮助很大,我认为它应该得到自己的答案:我已经有了cProfile生成的.pstats文件,我不想用pycallgraph重新运行这些文件,所以我使用了gprof2dot,得到了很好的svgs:
$ sudo apt-get install graphviz
$ git clone https://github.com/jrfonseca/gprof2dot
$ ln -s "$PWD"/gprof2dot/gprof2dot.py ~/bin
$ cd $PROJECT_DIR
$ gprof2dot.py -f pstats profile.pstats | dot -Tsvg -o callgraph.svg
还有BLAM!
它使用点(与pycallgraph使用的相同),因此输出看起来类似。我觉得gprof2dot丢失的信息更少:
获取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文档
根据乔·肖(Joe Shaw)关于多线程代码无法按预期工作的回答,我认为cProfile中的runcall方法只是围绕着已配置的函数调用执行self.enable()和self.disable()调用,因此您可以简单地自己执行,并在对现有代码的干扰最小的情况下使用任何代码。