目录
所有的 Python 都很慢,但有些比其他的更快
Python 并不是最快的编程语言,因此任何性能提升都是有帮助的,尤其是在大规模运行时。事实证明,根据你安装 Python 的来源不同,其性能可能会有很大差异:选择错误的 Python 版本可能会使你的速度降低 10-20%。
让我们来看一些数据。
Python 3.12(2024 年 6 月)
我使用“官方”Python Docker 镜像(python:3.12
)和 Ubuntu 22.04(ubuntu:22.04
)对 Python 3.12 进行了一个快速实验。
Python 3.12 构建 | Pystone(越高越好) |
---|---|
Docker python:3.12 | 670,000 |
Ubuntu 24.04 | 750,000 |
Ubuntu 24.04 的构建明显更快!
旧版本的测试
在之前的 Python 版本中,结果有所不同。对于 Python 3.9,存在性能差异;而对于 Python 3.10,我没有看到任何差异。
比较 Python 的构建(2021 年 2 月)
我使用 pyperformance 套件 中的三个基准测试,对四种不同的 Python 3.9 构建进行了测试(代码在这里):
python:3.9-buster
,官方的 Python Docker 镜像。- Ubuntu 20.04,通过
ubuntu:20.04
Docker 镜像。 - 在
ubuntu:20.04
上的 Anaconda Python。 - 在
ubuntu:20.04
上的 Conda-Forge。
如果你不熟悉 Conda,它是一个包含几乎所有库和可执行文件(包括 Python)的预编译库的打包系统,除了标准的 C 库。创建 Conda 的公司 Anaconda 提供了一个包通道,还有一个名为 Conda-Forge 的社区项目,提供了 Python 和数千个其他包。
所有基准测试都在 Docker 容器内运行,运行在 Fedora 33 上,使用 Intel Xeon CPU E3-1226 v3 @ 3.30GHz。Docker 在 Fedora 上的性能开销似乎出奇地高,但这应该在同一基准测试的运行中是相同的,而且我在之前使用 Podman的基准测试中得到了类似的结果。
以下是结果,包括平均值和标准差;每个运行进行了 10 次,但我也进行了多次运行,结果相似。越低越好,因为我们测量的是耗时。Conda-Forge 的 Python 最快,其次是 Ubuntu 20.04;官方的 Docker Python 镜像最慢。
Python 构建 | 2to3 | django_template | unpickle_pure_python |
---|---|---|---|
Conda-Forge | 491ms ± 3ms | 78ms ± 0.8ms | 514us ± 5us |
Ubuntu 20.04 | 512ms ± 3ms | 80ms ± 0.7ms | 537us ± 7us |
Anaconda | 523ms ± 5ms | 86ms ± 2.3ms | 550us ± 3us |
python:3.9-buster | 543ms ± 3ms | 92ms ± 0.6ms | 590us ± 12us |
为什么会有这些差异?
事实证明,编译 Python 以获得最大性能实际上非常复杂:它涉及基于实际代码运行的配置文件引导优化(PGO),以及可以调整的各种编译器选项。
其中一个选项是 Python 实现的核心是在共享库中,还是在 python
可执行文件本身中。共享库版本往往较慢。
Python 构建 | python 是否链接到 libpython.so ? |
---|---|
Conda-Forge | 否 |
Ubuntu 20.04 | 否 |
Anaconda | 否 |
python:3.9-buster | 是 |
Fedora 和 RHEL 也使用共享库版本的 Python。然而,它们——以及未来的 Python 3.10 默认情况下——使用 -fno-semantic-interposition
选项来加速。官方的 python
Docker 镜像尚未使用此选项。这至少解释了为什么官方的 Docker 镜像如此慢。
然而,这还不足以解释所有这些性能差异,以及其他构建之间的差异。其他可能的原因包括它们是否进行了配置文件引导优化、其他编译器标志、编译器版本、glibc 差异等。
Python 3.10(2022 年 5 月)
Python 3.10 有不同的优化设置,我能够使用更新的 Debian(Bullseye 已取代 Buster)和 Ubuntu(22.04)版本以及更新的编译器进行测试。因此,我决定使用更新的镜像重新运行这些测试。这些结果在绝对意义上可能与 3.9 的数字不可比;更有用的是将它们相互比较。同样,越低越好:
Python 构建 | 2to3 | django_template | unpickle_pure_python |
---|---|---|---|
Conda-Forge | 479ms ± 35ms | 55.6ms ± 1.0ms | 367us ± 5us |
Ubuntu 22.04 | 486ms ± 29ms | 55.6ms ± 1.4ms | 379us ± 5us |
python:3.10-bullseye | 471ms ± 32ms | 55.4ms ± 1.7ms | 358us ± 4us |
在 Python 3.10 中,我没有看到不同 Python 构建之间有意义的差异。
结论:谨慎选择 Python 版本
我对 Python 3.9 和 3.12 不同构建之间的性能差异感到惊讶。也许这是我的基准测试失败,但它们确实配置不同。而且还有许多其他构建我没有测试,比如为 Ubuntu 提供额外 Python 版本的 deadsnakes
PPA,RedHat Enterprise Linux 中的 Python 等等。结果似乎也随时间变化,因为不同的 Linux 发行版和打包者切换了版本、编译器和编译器版本。你最好的选择是:为你自己的应用程序进行基准测试。