欢迎访问本站,持续更新中…

我以为 Python 3.14 只是常规更新,结果有人把它编译到了裸金属

2026-07-07

上周刷 GitHub Trending,看到一个叫「pon」的项目。README 第一行就让我愣住了:

Python 3.14, compiled to metal — JIT & AoT native compiler and runtime in Rust. There is no interpreter and no bytecode.

没有解释器。没有字节码。

我盯着这句话看了至少半分钟。Python 之所以是 Python,就是因为有解释器、有字节码、有运行时动态性。没有这些,它还叫 Python 吗?

从「又一个 JIT 项目」到「这是真家伙」

说实话,最开始我以为是另一个挂着 Python 名字的玩具项目。这类项目并不少见——有人尝试用 Rust 重写 CPython 的某些部分,有人做个 JIT 原型发篇博客就结束了。大多数走不到真正的可用状态。

但 pon 不太一样。

项目由 can1357 开发,用 Rust 编写,核心架构是:Python 3.14 源码 → ruff 解析器 → 统一 IR → Cranelift 后端 → 机器码。整个链路里没有任何字节码 interpreter,没有 ceval 循环,没有 PyFrameObject。代码直接从 AST 降到 IR,再从 IR 到机器码,走 JIT(进程内编译)或 AoT(编译成独立可执行文件)两条路径。

我仔细看了它的架构图:

source.py
    │
ruff parser (Python 3.14 语法)
    │
AST ──> PON IR(统一的中间表示)
    │
    ├── JIT: cranelift-jit ──> 进程内执行
    │
    └── AoT: cranelift-object ──> 原生可执行文件
    │
pon-runtime(对象模型 + 内置函数)
pon-gc(Green Tea 垃圾回收器)

关键点在于 「统一的 IR」,JIT 和 AoT 走的是同一套 IR,同一套运行时 ABI。这意味着你写一段 Python 代码,既可以在开发时 JIT 跑,又可以 build 成独立的二进制文件分发——像 Go 或者 Rust 一样。

一张架构示意图,展示 Python 源码经过 ruff 解析器、PON IR、Cranelift 后端、再到 JIT/AoT 执行的完整编译链路,深色技术风

没有 GIL,没有引用计数——但代价是什么

CPython 最被人诟病的两个设计就是 GIL(全局解释器锁)和引用计数内存管理。pon 在这两个问题上都做出了激进的选择:

内存管理:Green Tea GC(垃圾回收器),不是引用计数。

CPython 的对象头里有一个 ob_refcnt 字段,每次对象被引用或解引用时都要原子增减这个计数器。这是 CPython 确定性析构的基础,也是大量性能开销的来源。

pon 直接去掉了 refcount 头,使用 Green Tea 垃圾回收器来管理对象生命周期。GC 的堆是所有 Python 对象的唯一所有者。在 tier-0(基线)模式下,使用保守的栈扫描(扫描栈上的每一个指针),配合安全点上的寄存器刷新 trampoline;在 tier-1(优化)模式下,升级为 Cranelift 的精确栈映射。

没有 GIL:但也不是无锁自由。

因为 pon 不是基于解释器的,没有 ceval 循环,自然也就没有 GIL。但线程安全并不等于无锁——对象模型中的某些并发操作仍然需要同步。目前 pon 的并发模型还在积极开发中,但至少架构上不受 GIL 的约束。

我最初判断其实是错的。我以为去掉 GIL 和引用计数后,性能应该能大幅领先 CPython。但实际看测试结果,pon 的目标不是「跑得比 CPython 快很多」,而是「通过编译优化逐渐超越 CPython」。

那两天看 pon 的代码其实挺消耗精力的。每次看到一个设计决策,都要想:CPython 是怎么做的,pon 为什么换了一种做法,换做法的代价是什么?

我坐回工位盯着天花板看了几秒。这家项目不是在「优化 Python」,是在重新实现一个 Python——从解析器到运行时到 GC,全链路重写。

字节精确差分测试:不妥协的验证方式

pon 最让我震撼的设计不是性能,而是测试策略。

项目使用「字节精确差分测试(byte-exact differential testing)」来保证正确性。具体来说:对同一段 Python 代码,分别在 pon 和 CPython v3.14.0 上运行,然后逐字节对比两边输出的结果。任何字节不一致都算测试失败。

这不是某个部分的抽样验证,而是作为 CI 出口门的硬性要求。README 里明确说:

Both paths print the same bytes CPython would. That property is not aspirational — it is the exit gate of the conformance suite.

我跑了几个简单的测试——print("hello, world")、基本的数学运算、列表操作。cargo run -p pon -- run hello.pypython3 hello.py 的输出完全一致。

但当我尝试一些边缘情况时——比如异常处理、生成器、闭包——pon 的行为就有点微妙了。团队在 Status 里明确标注了当前支持和不支持的功能。这个透明度对我来说是个很强的信号:项目知道自己在做什么,也知道自己还没做到什么。

一个开发者在终端窗口中运行 Python 代码,左右分屏对比 pon JIT 和 CPython 的输出结果,深夜编程场景

选择的天平:为什么不是 Mojo,不是 Julia,而是 pon

有人可能会问:如果你想要一个高性能的 Python 替代品,为什么不直接用 Mojo 或者 Julia?

这个问题我想过。Mojo 是 Modular 推出的 Python 超集,有 MLIR 加持,有完整的编译器基础设施。Julia 有 LLVM 后端,有类型推导,有原生性能。看起来都比一个刚起步的社区项目靠谱。

但我犹豫了一段时间后,选择了关注 pon。原因有三:

第一,语法兼容性。 pon 的目标是跑 Python 3.14 的语法,用 ruff 解析器去解析标准 Python 代码。你不用学新语法,不用改已有代码。Mojo 虽然兼容部分 Python 语法,但本质上是一门新语言。

第二,单二进制分发。 pon build 的输出是独立可执行文件。这在部署场景下非常有吸引力——不需要用户装 Python 环境、不需要 pip install、不需要 virtualenv。写一个 Python 脚本,编译成一个二进制,扔给用户就能跑。这个体验是 CPython 永远给不了的。

第三,循序渐进的设计路径。 pon 没有一步到位想取代 CPython。它的 tier-0 基线模式保证正确性(用字节精确差分测试兜底),然后 tier-1 才做类型特化、内联缓存、OSR。这种「先正确,再优化」的路线,比一上来就声称「比 Python 快 100 倍」的项目要可信得多。

但我也必须承认妥协。pon 目前还很早期,大多数第三方库(numpy、pandas、flask 等)都不能直接用。它主要能跑的是一些纯 Python 代码和标准库的子集。距离生产可用还有相当长的路。

一个二进制可执行文件的图标,旁边有 Python 代码片段,表示将 Python 编译为原生可执行文件的过程,扁平设计风格

这不只是另一个 JIT 项目

我现在对 pon 的看法跟最开始完全不同了。

最开始我以为是又一个「用 Rust 重写 Python」的玩具,后来发现它是一个真正的编译器和运行时基础设施。再后来我意识到——它代表了一种可能性:Python 的未来不一定绑在 CPython 的 ceval 循环上。

CPython 的架构已经快 35 年了。PEP 744(JIT)在 3.13 里尝试了 tier-2 优化器,但还是基于字节码的。pon 选了一条完全不同的路——抛弃字节码,从语法树直接编译到机器码。这条路能不能走通现在还不知道,但它至少证明了一件事:Python 3.14 的语法可以被编译,可以被优化,可以被交付成单二进制文件。

后来我一直在想,如果 pon 项目能坚持到生产可用,Python 的部署体验会发生多大变化?但那是很远的事。现在能看到的是——有人正在用 Rust 和 Cranelift,从底层重新想象 Python 应该怎么跑。而且字节精确差分,一行都没少。

关于维基框架

维基框架(Wiki Framework)是一套面向复杂业务场景的轻量级开发框架,支持多语言、多协议、多部署形态。适用于企业级应用开发、微服务架构、云原生部署等场景。