Python 3.13 获得了 JIT
Python 3.13 正在获得一个实验性的“copy-and-patch” JIT 编译器,目前带来的速度提升较为温和,约为 2–9%,但被视为未来更大优化的重要基础。评论者就 CPython 与 V8 或 PyPy 等高度依赖 JIT 的运行时相比到底还能被推到什么程度展开争论,考虑到 Python 高度动态的语义、对 C 扩展的依赖,以及对生态兼容性的维护需求。许多人仍认为渐进式提升是有价值的——尤其是跨多个版本累积起来时——而另一些人则质疑,要获得显著性能飞跃,是否最终需要更深层的改动或替代实现。
性能影响与预期
- CPython 3.13 中新的 copy-and-patch JIT 在初始基准测试中显示出约 2–9% 的速度提升。
- 一些人认为这已经很有意义,尤其是考虑到 CPython 基于 C 且改动很小;另一些人则觉得它与 PyPy 或 GraalPython 等声称有数倍提升的替代方案相比并不令人满意。
- 其初期影响有限:只有包含向后跳转的函数(即像
while/for这样的循环)会被 JIT 编译。 - 几条评论强调这只是基础工作;即使没有任何单一版本足够戏剧性,多个版本中的小幅提速累积起来也可能非常可观。
JIT 设计与技术取舍
- 该 JIT 使用“copy-and-patch”/模板式方法:将 C 实现的操作码编译成可重定位的代码片段,再在运行时针对特定的 Python 字节码序列拼接起来。
- 这重用了现有解释器逻辑,降低了新增复杂度,并避免在运行时分发 LLVM(LLVM 工具只在构建时需要)。
- 它主要消除了解释器分发开销;更深层的优化(例如指令融合、微操作、多层级 JIT)被讨论为可能方向,但尚未实现。
- 有人质疑,如果没有“完整”的优化型 JIT 和更激进的 IR 级分析,copy-and-patch 设计能走多远。
与其他运行时和实现的比较
- 讨论中提到的其他带 JIT 或替代的 Python 运行时包括:PyPy(在其基准上几何平均约快 4.8 倍)、GraalPython(在 pyperformance 上约快 4.3 倍)、Jython、IronPython,以及各种 AOT 工具(Nuitka、mypyc、Shedskin、Numba、Cython)。
- 由于兼容性(尤其是 C 扩展)、启动预热行为以及维护成本,没有任何替代 VM 实现对 CPython 形成广泛替代。
- JavaScript 引擎(V8、JavaScriptCore、SpiderMonkey)被用作证据,说明动态语言可以快得多,但它们面临的原生扩展约束更少,而且得到了巨额企业投入。
动态类型、类型提示与优化限制
- Python 的动态性(函数可重新赋值、猴子补丁、运行时添加字段、装箱整数)被反复提及,作为接近 C 级性能的核心障碍。
- 可选类型提示存在,但并不可靠,且主要由外部工具(如 mypy)强制检查;目前的注解不足以支持重大的 JIT 优化。
- 有人建议 JIT 应当像现代 JS 引擎那样,更多依赖运行时剖析与守卫条件。
生态系统、打包与 C 扩展限制
- 一个主要主题是:Python 在许多工作负载中的速度其实已经来自 C/C++/Fortran/Rust 扩展(NumPy、PyTorch、BLAS 等),Python 主要充当“胶水”。
- 这个 C API 既是优势也是重大限制:它暴露了 CPython 的内部结构,使激进的 VM 改动变得困难,也让替代实现为了兼容而付出高昂成本。
- 讨论中还提到打包与部署方面的困扰(virtualenv、Poetry、Docker、缺少简单的跨编译/单文件二进制工具),有时被认为比原始解释器速度更紧迫。
语言角色、理念与社区反应
- 许多人认为 Python 对常见的 IO 密集和集成型任务来说已经“足够快”;而当性能真正重要时,人们会转向原生库或其他语言。
- 也有人担心 Python 在原始速度上正被 Rust、Go、Java,甚至 JS 拉得太远,并希望这个 JIT 只是更激进优化工作的开始。
- 关于复杂度也存在争论:早期 CPython 设计更偏向简洁而非速度,但大规模使用(尤其在数据和 ML 领域)以及新的企业资金正在推动更复杂的内部实现。