认识 TypePHP 这个让 PHP 跑得更快的新编译器
人们早已习惯听到“对于大多数使用场景,PHP 已经足够快”这种说法,但与 Go、Rust 或 C++ 等编译型语言相比,很少有人会真正称 PHP 为高性能语言。如今,这一说法又多了一分动摇的理由。Swoole 背后的团队最近开源了 TypePHP,这是一款能够把日常编写的 PHP 代码转换为原生二进制文件的编译器,不再像往常一样通过解释器运行代码。
在急于把它与 JavaScript 生态中的 TypeScript 相比较之前,需要先澄清一点:两个项目都源于相似的不满,但解决问题的方式截然不同。TypeScript 为 JavaScript 增加类型安全,让代码编写过程更加可靠,随后再将其转译回普通 JavaScript。TypePHP 则更进一步——它会把 PHP 代码真正编译为 CPU 可以直接执行的原生机器指令,中间不存在重新转换回 PHP 的步骤。
TypePHP 究竟是什么
简而言之,TypePHP 是一款预先编译(Ahead-Of-Time,AOT)编译器。它先把 PHP 源代码转换为 C++,再将 C++ 编译为原生机器码。这与当今 PHP 的常规运行方式有着根本区别:普通 PHP 代码会经过 Zend 解释器,并在运行时执行操作码。

下面是一组简单的并列对比:
- 普通 PHP:编写代码 → 编译为操作码 → Zend Engine 在运行时逐条读取并执行操作码。
- TypePHP:编写代码,仍然使用开发者熟悉的 PHP 语法 → 编译为 C++17 → 再次编译为原生二进制文件 → 直接在 CPU 上运行,不再需要读取操作码。
值得关注的是,TypePHP 保留了人们熟悉的 PHP 语法,同时加入了编译期类型信息。这使编译器能够针对代码中承担大量计算的部分,生成静态类型且经过优化的 C++ 代码。
至于 PHP 中那些经常依赖的动态特性,例如反射和内部函数,TypePHP 也提供了相应处理方式。动态值、内部函数、反射和对象元数据仍然可以通过名为 PHPX 的中间层与 Zend 运行时互操作。因此,TypePHP 并未完全抛弃 PHP 的动态特性——只是函数一旦完成编译,就不再以 Zend 操作码的形式执行。
另一个值得注意的细节是:TypePHP 完全使用 PHP 编写,并且实现了完整的自举。tpc 编译器二进制文件由 TypePHP 编译该编译器自身的源代码生成,编译器内部没有作为胶水层存在的 C 或 C++ 代码。
它并不只是“PHP 版 TypeScript”
本文标题借用了 TypeScript 进行类比,因为这是一种便于理解的思维捷径。不过,为了建立准确预期,有必要明确两者之间的差异:
- TypeScript 是 JavaScript 的超集,转译回普通 JavaScript 后,仍然运行在相同的 JavaScript 引擎上,例如 V8 等引擎。
- TypePHP 并非只在 PHP 之上增加类型注解,而是把代码编译为原生二进制文件,而不是重新生成
.php文件。 - TypeScript 主要关注开发阶段的类型安全,TypePHP 则主要关注生产环境的运行时性能。
- TypePHP 的输出可以是独立可执行文件、PHP 扩展或共享库,而不只是经过转译的源文件。
因此,更准确的类比是:TypeScript 像一道“护栏”,帮助开发者编写更安全的 JavaScript 代码;TypePHP 则像一名“翻译器”,把 PHP 代码转换成 CPU 能够直接理解的形式。
PHP 开发者为什么应该关注
过去,当项目需要极致性能时,常见做法是使用另一种语言重写热点路径,例如 Go、Rust,或者手写 C 扩展。TypePHP 提供了一条值得关注的中间路线:
- 标量类型
int、float和bool可以直接映射为原生 C++ 类型int64_t、double和bool,从而显著加快高强度数值运算。 - 它支持
BigInt、Decimal和BigFloat等高精度类型,并为这些类型提供专用的类型化运算符和方法 API。 - 它提供
std::array、std::vector、std::map和std::unordered_map等强类型容器。在确实需要时,这些容器能够提供比普通 PHP 数组更高效的数据结构。 - 编译后的二进制文件无法反编译回源代码。对于需要分发商业软件而又不希望公开源码的场景,这是一项切实的优势。
- 同一套代码可以编译成三种不同的输出:独立可执行文件(
bin)、PHP 扩展(ext)或共享库(lib),因此一个代码库可以满足多种部署需求。
一个简单示例说明它为何如此不同
可以设想这样一个处理过程:更新数组中的数百万个元素,例如在大型库存系统中重新计算商品价格,或者为每日报表聚合数据。
使用普通 PHP 数组时,每一次元素访问都会经过 PHP 的动态访问机制,而这套机制本身存在额外开销。TypePHP 团队记录的一项基准测试比较了使用普通 PHP 数组和 TypePHP 的 std::array 大规模更新元素的性能。在该测试中,std::array 的速度约为普通 PHP 数组的 10 倍。
整体编译流程大致如下:
- 解析并验证 PHP 代码,以及必要时由
.stub.php文件提供的类型声明。 - 编译器收集代码中发现的所有声明。
- 把函数体和常量“降级转换”为 C++17。
- 原生编译器把 C++17 代码转换为二进制文件,同时复用目标文件和预编译头(PCH)缓存。
- 最终输出可以是可执行文件、PHP 扩展、共享库,甚至是 WASI 组件。
对于包含大量重复数值运算的代码,例如报表计算、批量数据处理或大型数组操作,性能提升往往会比主要执行数据库查询或 API 调用的代码明显得多。在后一种场景中,瓶颈通常本来就不在 PHP 的 CPU 计算上。
尝试之前需要了解什么
在急于把 TypePHP 引入生产项目之前,还需要注意以下几点:
- TypePHP 仍处于积极开发阶段。它有意支持一个经过定义和测试的 PHP 子集,而不是宣称能够完全兼容所有高度动态的 PHP 程序。
- 在现有应用中采用它之前,值得先阅读其兼容性模型和不受支持的功能列表。
- 它对 PHP 版本的要求相当明确:支持 PHP 8.4 及以上版本,但不包括 PHP 8.6。
- 该项目使用 GNU General Public License v3.0 发布,属于开源项目,可以免费使用。不过,如果计划将其用于商业产品,仍应仔细检查许可证条款。
- 项目实际发布的时间早于原计划。Swoole 团队原本计划在 2026 年 10 月左右发布 Beta 版本,但最终提前开源了该项目。
结语
没有必要在本周就急着把所有项目迁移到 TypePHP。但如果 PHP 代码承担着沉重的计算负载,例如大规模数据处理、密集型数值计算,或者代码库中长期存在性能瓶颈的部分,那么这个项目值得持续关注。
有一点已经十分明确:过去那种“PHP 很慢”的论调越来越难以站得住脚。PHP 先是拥有了 OPcache,随后引入 JIT 编译器,如今又通过 TypePHP 获得了原生编译路径。PHP 的发展方向表明,性能正在受到远比过去更加严肃的重视。