Python 3.15有多快?
Miguel Grinberg在Python 3.15上针对多种工作负载和硬件重新运行了他的基准测试套件,并报告了解释器在哪些方面变快、哪些方面没有变快。图表并排展示了单线程和多线程测试。
中文
复制

发布于 2026 年 10 月 5 日,分类:
又到十月了,这意味着又到了试跑新版 Python 的时候(严格来说,我用的是 3.15.0rc3,正式版 3.15 还要过几天才发布)。和一年前写 Python 3.14 性能那篇文章时一样,今天我分享一轮新的非正式 Python 基准测试,把 Python 3.15 与一路回溯到 3.10 的各个旧版本解释器做个对比。
如果你对图表不感兴趣,只想看我的分析,可以直接跳到文末的结论部分。
基准测试
我刚刚把这个基准测试称为“非正式”。这是什么意思?
想要客观、普适地衡量一门编程语言的性能是不可能的。你能做的只是写一些程序、跑一跑,得到它们的性能数据。别的程序可能表现出相似的性能特征,也可能不相似,这无从得知。我做这个基准测试,只是想感受一下 Python 各版本之间的性能变化,但我要说清楚:我并不打算给 Python 解释器做一份全面的性能画像。
这次基准测试我会跑两个程序,分别叫 fibo.py 和 bubble.py,你可以自己查看。它们和以往各轮基准测试用的是同一批程序。第一个计算斐波那契数列中的数字,第二个用冒泡排序算法给数字排序。
我选这两个程序,是想让它们分别代表两类算法。斐波那契计算用的是递归,而我发现递归在 Python 解释器里效率偏低。另一边,冒泡排序只用 for 循环,不涉及递归。还有一些其他类型的程序,这个基准测试没有覆盖。特别要说明的是,我没有把 I/O 密集型代码纳入其中。
最近几个 Python 版本的部分性能提升与多线程有关,因此我还为每个程序写了一个多线程版本,总共就是四组不同的测试。
测试矩阵
完整的测试矩阵其实相当复杂,因为我需要在所有 Python 版本下运行这四组程序变体,还要为支持 JIT 和 free-threading 的版本额外跑这两种模式。我也习惯在 PyPy 下跑一遍,因为在此前几轮这个基准测试中,这个解释器的性能表现都相当亮眼。为了把 Python 的性能放到更大的生态里看,我还把这两个程序移植到了 JavaScript(Node.js)和 Rust。
以下是我实际使用的完整测试矩阵:
- 2 个测试脚本
- fibo.py:用递归计算 Fibonacci 数
- bubble.py:对一组随机生成的数排序,不用递归
- 2 种线程模式
- 单线程
- 4 个并行线程
- 6 个 Python 版本,外加近期版本的 PyPy、Node.js 和 Rust:
- 3 种 Python 解释器
- 标准
- Just-In-Time(JIT):仅限 CPython 3.13+
- Free-threading(FT):仅限 CPython 3.13+
看过我之前基准测试的读者可能记得,我的矩阵里还有一个 Linux 与 macOS 的维度。鉴于前两轮测试中两者没有明显差异,这次我决定去掉 macOS 测试,所有测试都在我的 Linux 笔记本上执行,机器是 Intel Core i5 CPU,跑的是 Gentoo Linux。
我衡量每个参测对象性能的方法是:把测试程序跑三遍,取三次耗时的平均值。下面给出的结果表格中,我还会列出相对 3.15 版本的速度差异,在合适的时候也会列出相对某个解释器上一版本的速度差异。速度比较用一个简单的比值表示:1x 表示速度相同,0.5x 表示速度减半(也就是耗时翻倍),2x 表示快一倍(换个说法就是耗时减半),以此类推。希望这样讲够清楚。
测试 1:fibo.py,单线程
开始吧。第一个测试计算前 40 个斐波那契数。
| fibo(40) - 1 线程 | 耗时(秒) | 对比 3.15 | 对比上一版 |
|---|---|---|---|
| 3.10 | 15.9442 | 0.44x | |
| 3.11 | 9.4058 | 0.74x | 1.70x |
| 3.12 | 8.8545 | 0.78x | 1.06x |
| 3.13 | 8.8174 | 0.79x | 1.00x |
| 3.14 | 7.1659 | 0.97x | 1.23x |
| 3.15 | 6.9361 | 1.03x | |
| pypy3.12 | 1.2517 | 5.54x | |
| node-26.3 | 1.3899 | 4.99x | |
| rust-1.97 | 0.0898 | 77.24x |
下图是上述速度的图表形式:

从这些结果可以看出,在这个测试中,Python 3.15 只比 3.14 快了一点点,大概不足以说明问题。和往年观察到的一样,PyPy 3.12 的性能简直离谱,达到 3.15 的 5.5 倍,甚至还小幅领先 Node.js。Rust 则毫无意外,不过知道极限在哪里总是好事。
把每个 Python 版本与上一版对比,会发现一个有意思的细节。真正比前一版有显著性能提升的只有 Python 3.11 和 3.14 两个版本。从图表里能清楚看到这一点:某根柱子的高度相比前一根有明显下降。其余版本要么速度持平,要么只有小幅提升,所以总体来看一直在进步。
下一组结果展示的是 Python 的 JIT 和 free-threading(FT)版本在同一测试上的进展。注意,这两种 Python 解释器变体是 3.13 才引入的,所以可评估的版本范围小得多。
| fibo(40) - 1 线程 | 耗时(秒) | 对比 3.15 | 对比上一版 |
|---|---|---|---|
| 3.13 JIT | 8.8339 | ||
| 3.14 JIT | 7.1587 | 1.23x | |
| 3.15 JIT | 5.7625 | 1.20x | 1.24x |
| 3.13 FT | 12.0368 | ||
| 3.14 FT | 7.1185 | 1.69x | |
| 3.15 FT | 7.0298 | 0.99x | 1.01x |
下面是包含这些结果的图表:

其中最值得关注的一点是,3.15 解释器的 JIT 在同一测试中比标准解释器更快,这在往年并不成立。1.20 倍的提速不算小,看到这个结果相当令人兴奋。
自由线程这边没什么可期待的,毕竟这个测试是单线程的。但可以说,自由线程解释器的性能与 3.14 大致相当。
测试 2:bubble.py,单线程
来看第二个测试。下面是单线程冒泡排序测试的表格和图表,配置为对 10,000 个随机数排序:
| bubble(10000) - 1 thread | 时间(秒) | 对比 3.15 | 对比上一版本 |
|---|---|---|---|
| 3.10 | 3.9918 | 0.49x | |
| 3.11 | 2.6237 | 0.75x | 1.52x |
| 3.12 | 2.7341 | 0.72x | 0.96x |
| 3.13 | 2.833 | 0.70x | 0.97x |
| 3.14 | 2.0575 | 0.96x | 1.38x |
| 3.15 | 1.9716 | 1.04x | |
| pypy3.12 | 0.1073 | 18.37x | |
| node-26.3 | 0.0643 | 30.66x | |
| rust-1.97 | 0.0391 | 50.42x |

和上一个测试一样,这里也能看到 3.15 相对 3.14 的性能提升非常小。同样也能看到,3.11 和 3.14 是近年来真正在性能上带来明显变化的两个 Python 版本。有些版本在这个测试上甚至出现了小幅退步。PyPy 依然很快,但在这个测试中 Node.js 更快。
下面的表格和图表展示了 Python 解释器 JIT 版和自由线程版的结果:
| bubble(10000) - 1 thread | 时间(秒) | 对比 3.15 | 对比上一版本 |
|---|---|---|---|
| 3.13 JIT | 2.5887 | ||
| 3.14 JIT | 2.3624 | 1.10x | |
| 3.15 JIT | 1.5435 | 1.28x | 1.53x |
| 3.13 FT | 4.1888 | ||
| 3.14 FT | 2.7248 | 1.54x | |
| 3.15 FT | 2.6808 | 0.74x | 1.02x |

这张图与第一轮测试反映的整体情况一致。3.15 的 JIT 再次跑出 1.28 倍于普通解释器的速度提升,相当可观。自由线程版本相比标准解释器出现了性能下降,但 3.14 解释器也有类似幅度的下降,所以这不算退步。前面说过,这其实关系不大,因为这项测试是单线程的,本来就不是那种能让自由线程解释器发挥优势的应用。自由线程解释器的性能理应与普通版本相当,从这个角度看,还有工作要做。
测试 3:fibo.py,多线程
现在把所有测试重跑一遍,但这次并行开 4 个线程。这项测试本就是为评估 Python 解释器的自由线程版本而设计的,所以非 Python 的几项就不跑了。
先取一个基线,在标准 Python 上跑多线程测试。说清楚一点:这些结果对 CPython 来说注定不好看,因为全局解释器锁(GIL)让线程之间无法真正并发。下面是多线程 Fibonacci 测试的结果和图表:
| fibo(40) - 4 线程 | 时间(秒) | 对比 3.15 | 对比上一版 |
|---|---|---|---|
| 3.10 | 67.2867 | 0.48x | |
| 3.11 | 49.726 | 0.65x | 1.35x |
| 3.12 | 38.7307 | 0.84x | 1.28x |
| 3.13 | 38.9421 | 0.84x | 0.99x |
| 3.14 | 31.8367 | 1.02x | 1.22x |
| 3.15 | 32.5421 | 0.98x | |
| pypy3.12 | 5.6385 | 5.77x |

这项测试中 3.15 比 3.14 略慢一点。单线程测试里我们已经看到,3.15 解释器只比 3.14 快一点点,所以总体可以说标准解释器的速度和 3.14 差不多。这里还能看到 PyPy 依旧把标准 Python 远远甩在后面,但多线程让它也按相近的比例慢了下来,因为 PyPy 的并发同样受 GIL 影响。
下面来看看 Python 解释器的 JIT 版和自由线程版在这个测试上表现如何。
| fibo(40) - 4 线程 | 耗时(秒) | 对比 3.15 | 对比上一版 |
|---|---|---|---|
| 3.13 JIT | 38.5661 | ||
| 3.14 JIT | 30.9696 | 1.25x | |
| 3.15 JIT | 27.1641 | 1.20x | 1.14x |
| 3.13 FT | 12.4376 | ||
| 3.14 FT | 7.3052 | 1.70x | |
| 3.15 FT | 7.235 | 4.50x | 1.01x |

Python 3.15 解释器的自由线程版比标准版快约 4.5 倍,3.14 上这个比例也差不多。这一显著的提速可以归因于解释器不再受 GIL 约束,线程并发因此更高效。
从这些结果还能看出第二点:带 GIL 运行的 JIT 版解释器,即便在多线程下也依然对标准版保持相近的优势,而这是 3.15 才有的新变化。
测试 4:bubble.py,多线程
还剩最后一组结果。以下是冒泡排序测试中标准解释器的表现:
| bubble(10000) - 4 线程 | 耗时(秒) | 对比 3.15 | 对比上一版 |
|---|---|---|---|
| 3.10 | 16.5959 | 0.51x | |
| 3.11 | 10.7541 | 0.79x | 1.54x |
| 3.12 | 10.979 | 0.77x | 0.98x |
| 3.13 | 11.1337 | 0.76x | 0.99x |
| 3.14 | 8.7198 | 0.97x | 1.28x |
| 3.15 | 8.4514 | 1.03x | |
| pypy3.12 | 0.5165 | 16.36x |

这同样与之前的结果大致吻合,3.15 只比 3.14 快了一点点。
有了这个测试的基准,再来看看 JIT 版和自由线程版:
| bubble(10000) - 4 线程 | 耗时(秒) | 对比 3.15 | 对比上一版 |
|---|---|---|---|
| 3.13 JIT | 10.3004 | ||
| 3.14 JIT | 9.9454 | 1.04x | |
| 3.15 JIT | 6.6417 | 1.27x | 1.50x |
| 3.13 FT | 8.0547 | ||
| 3.14 FT | 4.9934 | 1.61x | |
| 3.15 FT | 4.8549 | 1.74x | 1.03x |

这里 free-threading 版 3.15 解释器又一次快过标准版。提升幅度不如 Fibonacci 测试那么亮眼,但这类程序仍然是适合无 GIL 解释器的用例。
至于 JIT 的结果,它们似乎与这个解释器在其他所有测试中的表现一致,都显示 3.15 有大幅改进。
结论
希望你看这份 benchmark 看得还算有趣。除了一堆数字和花花绿绿的图表,你可能也在想,这些到底有什么实际意义。
在结束本文之前,我想说说我个人对这些数字的解读,因为你可能想知道升级到 3.15 是否值得,以及升级后能期待哪些改进。这一节我们离开确定性的领域,进入观点的地盘,所以请记住,换个人来看这些数字,解读可能和我完全不同!
免责声明说完了,我的感觉是:跑完这些测试之后,Python 3.15 相比 3.14 在性能上最多只能算小幅改进。我目前跑在 3.14 上的生产项目(比如这个网站)以后也许会升级,但这次拿到的结果并不像去年看到 3.14 那么亮眼的成绩时那样,让我急着去升级。
3.15 唯一有明显改进的地方是 JIT。但 JIT 仍然是实验性功能,用在生产环境并不明智。等它脱离实验阶段,我才会考虑在生产环境里用 JIT。
除了 JIT,这个版本并没有什么显著的性能提升。有些测试确实有小幅提升,但另一些出现了回退,所以我不认为这些微小波动会在真实项目中转化成可感知的性能变化。说实话,继续留在 3.14 几个月,甚至等到一年后 3.16 发布、再多一个版本可以评估,我也不觉得有什么损失。
不过,我确实打算把 3.15 当作日常主力解释器来用,说不定最后还会为了用上新特性而升级一些生产项目,比如类似 JavaScript 的解包推导式,或者惰性导入。
请我喝杯咖啡?
感谢访问我的博客!如果这篇文章对你有帮助,欢迎通过 Buy me a coffee 一次性小额打赏,支持我的工作,也让我保持咖啡因充足。谢谢!