文章目录
📖 介绍 📖
最近关注 Python 动态的人大概都刷到过一条消息:那个折腾了好几年、终于在 3.15 里被官方宣传成「升级过」的实验性 JIT,可能要被从 CPython 主干里拿掉了。
第一反应通常很直接------「所以 Python 白干一场了?」或者「那我之前开的 JIT 是不是白折腾了?」
但这条消息里叠着好几层不同的东西:一条是社区提案被撤回,一条是 CPython 主干里的实验代码可能清理,还有一条是已发布正式版里的实际性能数据。三层混在一起传,结论很容易跑偏。
真正该关心的问题其实很朴素:这件事现在对你的生产环境有没有影响?那个开关今天还要不要开? 下文把官方文档、提案页、仓库实测和本机跑出来的数据摊开讲,帮你把该记住的部分和可以放下的部分分开。

🖥️ 演示环境 🖥️
- 🐧 系统:Ubuntu 容器(x86-64 Linux)
- 🐍 解释器:CPython 3.15.0rc2(python-build-standalone 预编译包)
- 🌍 网络:本地离线环境
📢 注意: 本文内容为个人学习笔记,仅供参考。附:读者须知
📒 时间线、状态查询与实测对照 📒
🧰 这件事的三个时间点,串起来才看得清
📜 一次撤回,落在一次正式发布之后
时间线其实很短,但每一个时间点的作用都不一样:
- 2024 年 4 月 :PEP 744《JIT Compilation》诞生,类型是 Informational(信息性提案)------只做记录和说明,不代表社区已就「要不要做、做到什么程度」达成正式共识。
- 2026 年 6 月 :Python 指导委员会(Steering Council)提出正式要求------想把 JIT 变成 CPython 里受支持、非实验的特性,就得拿出一个标准追踪(standards-track)提案,六个月内提交并被接受;否则主干里的 JIT 代码要被移除。
- 2026 年 7 月 2 日:PEP 836《JIT Go Brrr》提交,标准追踪类型。里面写得很细,比如要求到 3.17 首个 beta 时,JIT 加自由线程版本(自由线程指不使用全局解释器锁的构建方式)相对非 JIT 版本在 pyperformance 上至少要有 20% 的几何平均提升。
- 2026 年 10 月 9 日 :Python 3.15.0 正式发布,官方说明把实验性 JIT 当作亮点宣传------x86-64 Linux 上相对标准解释器有 7-8% 的几何平均提升(几何平均 = 多次测量取几何平均后得到的整体提升幅度),AArch64 macOS 上相对尾调用解释器有 11-12%。
- 2026 年 10 月 19 日 :PEP 836 状态改为 Withdrawn(撤回)。作者说明大意是:指导委员会对这类规模的提案门槛定得很高,他们个人没有精力把当前版本继续推下去。
- 2026 年 10 月 26 日:LWN 刊出报道,把这件事定性为「实验性 JIT 将被移除」,并指出主干相关工作会停止,清理大概率安排在 3.16 开发周期内。
所以时间线上有个错位:提案被撤回,发生在正式版发布之后。 3.15 里的 JIT 是已交付给用户的实现,撤回动的是「未来怎么把它扶正成受支持特性」的路径,不是把发出去的东西收回来。
📌 两个提案号,别搞混
中文技术圈一提到 PEP 编号就容易串。
| 提案 | 状态 | 性质 | 管的是哪一段 |
|---|---|---|---|
| PEP 744 | Draft(信息性) | 记录 2024 年那次实验性 JIT 的设计与现状 | 「当时是怎么做的」 |
| PEP 836 | Withdrawn | 标准追踪 | 「怎么把它变成受支持特性、要满足什么指标」 |
撤回的是第二个。第一个还静静地挂在提案索引里,标注自己是信息性提案。
🔬 「移除」到底指什么
这里是最容易被误读的一环。指导委员会给的那个六个月期限,针对的是主干里继续保留实验代码这件事------社区当时的顾虑写得很直白:主干里做实验,因为缺少统一设计、不确定行为和接口会怎么变,会让核心开发者、包维护者和使用者都难受。
所以「移除」指向的是 CPython 主干仓库里的实验实现和构建开关,而不是:
- 立刻从已经发布的 3.13 / 3.14 / 3.15 里把 JIT 抠掉;
- 让 PyPy 这类替代实现消失(那是完全独立的解释器实现);
- 意味着 Python 整体性能会退步。
我在写这篇文章的时候顺手查了 cpython 仓库的现状:Tools/jit 目录此刻仍在主干里(15 个文件,含 jit.h、_llvm.py、_stencils.py 等),该目录最近一次提交停在 2026 年 6 月 14 日。
GitHub 上近两周的动向也集中在 CI 和维护层面,比如 10 月 21 日一个把 macOS x86_64 从 JIT CI 里摘掉的改动,10 月 19 日一个把 JIT 优化器代码所有者从提案作者身上移除的改动。清理动作还没有真正落到主干代码上。
同时,3.16 的官方 configure 文档和 sys 模块文档里,--enable-experimental-jit 和 sys._jit 的说明目前也都还在。也就是说,文档层面同样还没动。
🚦 那个开关,今天到底要不要开 🚦
上面讲的是历史与未来。对使用者来说更现实的问题是:现在这个开关还有没有意义。
🔍 先学会查状态
好消息是,这个判断不需要猜。CPython 从 3.14 起提供了 sys._jit 这个模块,三个函数就够用:
python
import sys
if not hasattr(sys, "_jit"):
print("这个解释器没有 JIT 相关接口")
else:
print("available:", sys._jit.is_available()) # 编译时是否带了 JIT
print("enabled:", sys._jit.is_enabled()) # 本进程是否启用
print("active:", sys._jit.is_active()) # 当前最顶层栈帧是否跑在 JIT 代码里
三者的含义要分清:
is_available()是编译期属性,由构建时的开关决定:Windows 上是--experimental-jit,其他平台是--enable-experimental-jit。is_enabled()是运行期属性,可用环境变量PYTHON_JIT在启动时控制,0关闭、1打开。官方文档特别强调:这个变量会覆盖构建时的默认状态。is_active()只在当前栈帧真正执行 JIT 代码时才为真。官方文档把它定位为「仅供测试和调试使用」,并提醒反复调用它本身可能给出意外结果------因为这是 tracing(追踪式)JIT,调用它的位置会影响热点走向。
最后这条提醒很关键,我的实测数据就踩到了同一个坑。
📈 我在本机跑出来的对照
我在容器里用 uv 拉了一份 CPython 3.15.0rc2 的社区预编译包------uv 默认下载的就是 python-build-standalone 这套构建------然后查了它的构建参数:
text
--enable-experimental-jit=yes-off
yes-off 的意思是「JIT 编进来了,但默认不打开」。这意味着一个很常见的误解需要先纠正:你手头的 3.15 解释器里,JIT 是在的,只是默认关着;官方 3.15 那些宣传数字,是官方自己那套专门编译的版本跑出来的。
于是我做了三组对照,同一台机器、同一段代码,只切 PYTHON_JIT 环境变量:
bash
# 关闭(发行版默认)
python3.15 bench.py
# 打开
PYTHON_JIT=1 python3.15 bench.py
第一组是纯整数算术的热点循环。开关打开后,最小耗时从 1.34 秒降到 1.23 秒;换一轮跑,从 1.97 秒降到 1.41 秒。大约 10%~30% 的区间,波动不小。
第二组是字符串拼接,第三组是带异常处理的分支逻辑。这两组在开关打开后基本持平,差异在噪声范围内------没有出现负收益,也没有出现传说中那种数量级的提升。
更有意思的是第三个观察点:我按官方文档建议的方式,在热点循环内部 去采 sys._jit.is_active(),结果无论开关开还是关,返回的一律是 False。
我怀疑这里有两层原因叠加:一是 tracing JIT 需要先观测够多的执行路径才会把这段代码编译成机器码,而我采样的位置本身在循环里打断了这个过程;二是官方文档那句「反复调用可能给出意外结果」的警告说的正是这类情况。
换句话说,别指望用一个简单探针就能证明 JIT 有没有真的在跑,用基准对比来看更靠谱。
⚖️ 所以,能得出什么结论
把这几组数据放在一起,我的判断是这样的:
- 别把 JIT 当成性能开关。 在我这个纯算术热点上能看到十来个百分点的差距,在字符串和分支密集的代码上基本看不出差别。官方自己给 3.15 的口径也是「几何平均提升」这种统计值,同时明确写着:不同测试在开启 JIT 后,从「慢约 15%」到「快一倍以上」都出现过,忽略某个特定的微基准之后。你的代码快不快,跟它像不像官方基准里的用例,关系很大。
- 今天开它,主要风险是兼容性而不是性能。 提案被撤回这件事本身就说明,围绕它还有一堆没谈拢的问题------兼容性审查的时间点、平台一致性、用户可感知的行为差异、安全评审,这些都是指导委员会明确点名要求补充的。也就是说,这段代码是「实验性」不是修辞。
- 真要试,用环境变量而不是重新编译。
PYTHON_JIT=0/PYTHON_JIT=1在任何带 JIT 的解释器上都能即时生效,代价是零。上手前先查is_available(),如果返回False,说明你手上这个解释器压根没编进 JIT,查再多也没用。 - 别把 3.16 的动向当成紧急事件。 清理动作目前只停留在提案撤回和社区讨论阶段,主干目录、构建文档、
sys模块文档都还没动。真到动的那天,官方一定会提前在开发指南里给出迁移说明。
⚠️ 说明: 整理时点为 2026 年 10 月,CPython 的特性、提案状态与构建参数随时可能变化,请前往 PEP 索引 与 Python 官方文档 自行核实最新状态;本文所述仅代表整理时点的实测情况,仅供参考。
🛠 落到你自己的环境里,可以做的三件事
这三条不需要等 3.16 的结论,现在就能做:
一、把状态查询塞进健康检查。 下面几行可以直接抄进启动脚本或监控里,拿到的是解释器自己的能力说明,不是任何外部推测:
python
import sys
jit = getattr(sys, "_jit", None)
if jit is None:
status = "no-jit-interface"
elif not jit.is_available():
status = "built-without-jit"
elif not jit.is_enabled():
status = "available-but-disabled"
else:
status = "enabled"
print(status)
二、要做对比就自己测,别引用别人的数字。 官方给的是基准套件上的几何平均,你的业务代码是另一回事。比较时固定这几件事:同一台机器、同一份代码、只切环境变量、跑多轮取最小值而非平均值(最小值更接近真实上限),用 time.perf_counter() 而不是墙钟时间。
三、把 JIT 从关键路径上摘出来。 如果服务里确实开过它,那么解释器版本升级或主干清理落地时,行为有可能变。把它当成可开关的加速项 而不是依赖前提,出问题时至少还有一条退路。
至于要不要现在开------从我这边的实测看,收益不保证、风险可控、切换成本近乎为零,那就在自己的测试环境里试一轮,看真实数据再决定。但别把 3.15 宣传稿里的数字直接当成自己的预期。
⚓️ 相关链接 ⚓️
- XiaoqiangClub
- 一条命令跑完 Python 类型检查?uv 把包管理和类型检查接起来了
- PEP 836 -- JIT Go Brrr: The Path to a Supported JIT Compiler for CPython
- PEP 744 -- JIT Compilation
- Python 3.15.0 发布说明
- CPython 构建选项:--enable-experimental-jit
- sys 模块:sys._jit
- LWN:Python's experimental JIT to be removed
- Python 开发指南:各版本状态
【CANARY-1210】