Python 的实验性 JIT 要生变?那个开关现在还该不该开

文章目录

📖 介绍 📖

最近关注 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 有没有真的在跑,用基准对比来看更靠谱。

⚖️ 所以,能得出什么结论

把这几组数据放在一起,我的判断是这样的:

  1. 别把 JIT 当成性能开关。 在我这个纯算术热点上能看到十来个百分点的差距,在字符串和分支密集的代码上基本看不出差别。官方自己给 3.15 的口径也是「几何平均提升」这种统计值,同时明确写着:不同测试在开启 JIT 后,从「慢约 15%」到「快一倍以上」都出现过,忽略某个特定的微基准之后。你的代码快不快,跟它像不像官方基准里的用例,关系很大。
  2. 今天开它,主要风险是兼容性而不是性能。 提案被撤回这件事本身就说明,围绕它还有一堆没谈拢的问题------兼容性审查的时间点、平台一致性、用户可感知的行为差异、安全评审,这些都是指导委员会明确点名要求补充的。也就是说,这段代码是「实验性」不是修辞。
  3. 真要试,用环境变量而不是重新编译。 PYTHON_JIT=0 / PYTHON_JIT=1 在任何带 JIT 的解释器上都能即时生效,代价是零。上手前先查 is_available(),如果返回 False,说明你手上这个解释器压根没编进 JIT,查再多也没用。
  4. 别把 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 宣传稿里的数字直接当成自己的预期。

⚓️ 相关链接 ⚓️

【CANARY-1210】

相关推荐
2601_967987371 小时前
终端 IDE 卷到了新高度:个人免费,符号索引快 65%,内存省 95%
ide·python·免费·性能·rune
全栈陈序员1 小时前
【Python】基础语法入门(三十一)—— API 开发:用 FastAPI 构建 RESTful 接口
python·restful·fastapi
CSharp精选营1 小时前
.NET 接口从 800ms 干到 60ms:生产环境这几个优化点最关键
性能优化·c#·.net·efcore
懂点Tech9 小时前
ctfshow misc28:GIF 高度修改解题与脚本实现
开发语言·windows·python
comedate9 小时前
SMLib 的 Examples 导读:PyAPI / SM_API / SMLib 三组示例怎么读
python·cad·smlib·examples·sm_api
云和数据.ChenGuang9 小时前
Python 重写(Override)深度解析:从 MRO 到 super() 的完整机制
java·开发语言·人工智能·python·langchain·1024程序员节
川石课堂软件测试10 小时前
学习软件测试需掌握的一些知识
数据库·python·sql·功能测试·网络协议·mysql·http
万化冥合10 小时前
PyBox屏幕键盘如何辅助演示键盘操作?
python·计算机外设
车软学堂11 小时前
从测试转开发,到底要补什么
网络·人工智能·python·功能测试·单片机·车载系统·自动化