作者 | Martin Heinz
译者 | 陆离
编辑 | Jane
来源 | AI科技大本营(ID:rgznai100)
【导读】一直以来,诟病 Python语言的人经常说,他们不想使用的一个原因是 Python 的速度太慢了。不管使用哪一种编程语言,程序运行速度的快慢在很大程度上还是取决于编写程序的开发人员,以及他们编写高效程序的技巧和能力。
那这可以说是 Python 开发者们的问题吗?为了证实一些不正确的看法,我们接下来就带领大家一起看看想要提升 Python 程序的性能,加快运行速度 30%,有什么方法?
时序和性能优化
在开始优化任何一段 Python 程序之前,我们首先需要找出哪部分代码是拖慢整个程序运行速度的原因。有时候程序的瓶颈可能会很明显,但更多时候不那么容易被发现,为了快速地定位瓶颈来进行优化,下面提供了一些查找瓶颈的方法:
以下我们以一段实际的代码作为示例,它用于进行指数运算(来源于Python文档):
# slow_program.py
from decimal import *
def exp(x):
getcontext().prec += 2
i, lasts, s, fact, num = 0, 0, 1, 1, 1
while s != lasts:
lasts = s
i += 1
fact *= i
num *= x
s += num / fact
getcontext().prec -= 2
return +s
exp(Decimal(150))
exp(Decimal(400))
exp(Decimal(3000))
最简单的优化
首先,最简单的、最实用的性能优化的解决办法是利用 Unix 的 time 命令,time可以监控程序执行的时间:
~ $ time python3.8 slow_program.py
real 0m11,058s
user 0m11,050s
sys 0m0,008s
如果你只想给整个程序的运行计时,这是可行的,但通常来说还是远远不够的…
最详细的性能分析
另外一个可以利用的指令是 cProfile,但是它提供的信息又过于详细了:
~ $ python3.8 -m cProfile -s time slow_program.py
1297 function calls (1272 primitive calls) in 11.081 seconds
Ordered by: internal time
ncalls tottime percall cumtime percall filename:lineno(function)
3 11.079 3.693 11.079 3.693 slow_program.py:4(exp)
1 0.000 0.000 0.002 0.002 {built-in method _imp.create_dynamic}
4/1 0.000 0.000 11.081 11.081 {built-in method builtins.exec}
6 0.000 0.000 0.000 0.000 {built-in method __new__ of type object at 0x9d12c0}
6 0.000 0.000 0.000 0.000 abc.py:132(__new__)
23 0.000 0.000 0.000 0.000 _weakrefset.py:36(__init__)
245 0.000 0.000 0.000 0.000 {built-in method builtins.getattr}
2 0.000 0.000 0.000 0.000 {built-in method marshal.loads}
10 0.000 0.000 0.000 0.000 :1233(find_spec)
8/4 0.000 0.000 0.000 0.000 abc.py:196(__subclasscheck__)
15 0.000 0.000 0.000 0.000 {built-in method posix.stat}
6 0.000 0.000 0.000 0.000 {built-in method builtins.__build_class__}
1 0.000 0.000 0.000 0.000 __init__.py:357(namedtuple)
48 0.000 0.000 0.000 0.000 :57(_path_join)
48 0.000 0.000 0.000 0.000 :59()
1 0.000 0.000 11.081 11.081 slow_program.py:1()
...
在这里,我们使用 cProfile 模块和 time 参数来运行测试脚本,以便按内部运行时间(cumtime)对行数据进行排序。这会提供给我们很多的信息,在上图中你可以看到显示的行数大约只是实际输出的十分之一。因此,我们可以看出exp函数是耗时的罪魁祸首,现在我们可以更进一步地了解时序和性能优化了。
时序特定功能
既然我们知道性能瓶颈所在,那么我们可能希望给运行起来比较耗时的函数进行计时,而不用关注其余部分的代码了。为此,我们可以使用一个简单的 decorator(装饰器):
def timeit_wrapper(func):
@wraps(func)
def wrapper(*args, **kwargs):
start = time.perf_counter() # Alternatively, you can use time.process_time()
func_return_val = func(*args, **kwargs)
end = time.perf_counter()
print('{0:
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?


微信扫码登录