作者|Anthony Shaw
编辑|安翔
Python 3 比 Python 2 慢吗?哪个版本的 Python 3 速度最快?还有哪些措施可以提高速度?究竟哪个版本的 Python 是最快的?当然,“这取决于”多种因素,但它具体取决于什么,我们应当如何为自己的应用程序找到最快的 Python 版本呢?就这些问题,今天我来试着做一些测试。
使用 Python 性能测试程序
但是这个测试依然存在一些问题:
测试结果不易理解
测试不包括 PyPy
首先,执行指令 pip install performance 来 下载测试程序,然后执行以下指令:
pyperformance run --python= -o my_results.json
该指令将针对 Python 的目标版本多次运行一系列“真实”应用的测试程序,并记录测试结果的平均值。
在本文中,我主要对以下版本的 Python 进行了测试:
2.7.10,
3.4.4,
3.5.4,
3.6.1,
3.7(beta 2)。
此外,还测试了 PyPy(5.6)和 PyPy3(5.4.10)。
测试结果
我已经根据这套测试用例进行了测试,大家可以查看测试结果。当然,你也可以编写自己的测试用例并运行自己的测试。
我还编写了一个简单的脚本,用来获取性能数据文件列表,并为每个测试结果制作了非常直观的图表。我将这个脚本的代码放在了 GitHub 上(见文末链接)。
在所有图表中,结果都以秒为单位,数值越低说明性能越好。
关于完整的测试结果和图表,可以查看以下链接:
https://github.com/tonybaloney/performance_testing/tree/master/png
我认为很重要的测试都包含在其中了。其余的测试与已经进行的测试大同小异,已经包含在结论中了。
渲染 HTML 模板
django_html 测试将使用 Django 模板渲染引擎创建一个 150 行×150 列的 HTML 表格。它利用了 Django 引擎的内容和模板类。
PyPy 的测试结果显示,其运行速度比任何一个 CPython 的 Python 版本都快得多,而 PyPy3 则会比 PyPy 慢两倍。需要注意的是,Django 最近决定在 Django 2.0 及更高版本中将放弃对 Python 2 的支持,这意味着 PyPy 将不再与 Django 2 兼容。
启动时间
该测试主要用来测试 Python 解释器启动所花费的时间。如果你打算运行多个进程来打破 Python 的“GIL”约束,那么这将是非常重要的。
此处我先跳过 PyPy,尤其是 PyPy3,我会在文章末尾再进行探讨。
从上图可见,Python 2.7 的启动时间是最短的。
加密测试:crypto_paes
在加密测试中,你会发现 Python 2 相比 Python 3 的速度明显快得多。什么原因呢?因为加密需要大量的数字运算,而 Python 3 废弃了 32 位整型,取而代之的是长整型。
对于 PyPy 用户来说,你应该会注意到PyPy3 比 PyPy 慢 5 倍!
算法测试:n-queens
这个算法可能不会让所有人都舒心,用这个算法来进行测试,可能会勾起一些人当初在算法课上经历的不美好回忆,对此我只能说抱歉了。这个算法的规则实际上很简单,就是把 n 个“皇后”放在棋盘上,保证任意两个“皇后”都不在同一行、同一列或者同一斜线上,使她们攻击不到彼此。
在 CPython 系列中,Python3.7 的性能再次夺魁。此外,PyPy 和 PyPy3 的测试结果非常相似。
浮点运算
在浮点运算的测试中,我将人为地通过 math.cos(),math.sin() 和 math.sqrt() 函数创建繁重的浮点运算应用程序,总共创建 10 万个浮点对象。
从测试结果可以看出,PyPy 非常适合浮点运算,对于大量的数据处理、可预测的类型和方法以及循环,PyPy 展现出了杰出的性能。由于 Python 3.7 具有新的快速方法调用操作码,因此在 CPython 中,它的速度最快。
正则表达式
在正则表达式测试中,“我使用了网络上最流行的 50 个网页,并记录所有正则表达式操作。每个操作都有一个权重,它根据页面出现的热门程度以及加载每个页面时执行的次数计算得来。最后,使用 ROT13 对数据中的字母进行编码,这样不会影响正则表达式匹配其输入的方式。”
在这个测试中,我不知道 PyPy 出了什么问题,我很想知道其他人是否得到相同的结果!
更新:PyPy 团队看到了这篇文章,并在几个小时内解决了这个问题
@cfbolz @anthonypjshaw 解决了这个问题: https://t.co/9UuNj1Gd8F
Python 3 比 Python 2 更快吗?
是的! 在大多数测试中,Python3 都比 Python2 更快。但有几个例外情况值得注意,在加密测试中,由于整型数据类型的原因,Python 3 的速度比 Python2 慢了 1.35 倍,在启动时间测试中,Python3 则比 Python2 慢了 1.39 倍。
Python 3 启动慢的问题将会是 CPython 核心团队在 3.8 和 3.9 版本中主要解决的问题之一。
除了加密和启动时间测试之外,在其他的测试项目中,Python 3 的速度比 Python2 大约快 1.2-1.3 倍。改进后的 Python 3.7 升级版将会在今年年底面世。
既然 PyPy 快得多,为什么不是所有人都使用它呢?
PyPy 拥有即时(JIT)编译器,因此它比 CPython 快。JIT 编译器具有很大的好处,因为它们在执行可预测的重复性任务时非常高效。Python 性能测试的其中一个特点是,你需要多次运行同一段代码以使其准确无误,从而减少应用程序的错误边界。因此,PyPy 面对这样的测试性能更优。
JIT 编译器,尤其是 PyPy 的 JIT 编译器最显著的缺点是启动成本高。另一个缺点是许多 C 语言扩展程序缺乏兼容性。因为“Python”(CPython,官方的 PSF Python)是用 C 语言编写的,PyPi 上的许多第三方扩展利用了这一点。Numpy 就是一个很好的例子,Numpy 的大部分代码都是用优化的 C 代码编写的。当你执行 pip install numpy 命令时,它会使用本地 C 编译器为你的 Python 运行时建立一个二进制库,供 Python 程序使用。
由于 PyPy 是用 Python 编写的,很多模块根本无法在 PyPy 中工作,所以你需要经常进行检查。
此外,PyPy 也需要面对与 CPython 相同的挑战:从 Python2 向 Python3 转变。直到最近我仍然发现 PyPy3 不稳定,在测试中仍然会出现一些奇怪的结果。一些其他的软件包遇到了问题,比如 PyTest,因此它们放弃了对 PyPy3 的支持。
结论
Python 3.7 是速度最快的“官方”Python 版本,在我测试过的解释器中,PyPy 则是最快的。
如果 Python2 以后用得越来越少,即使 PyPy3 无法比 PyPy 更快,我也希望它在速度上有所提升。
最后,推荐我们精心打磨的 Python 课程,基于 Python 3 的,希望能帮到你。