TypePHP 编译器 https://swoole.com/aot/
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

12 KiB

简体中文 | English

TypePHP

PHP 原生 AOT 编译器

将 PHP 源码提前(AOT)编译为原生机器码,生成独立的可执行文件、PHP 扩展和静态库, 同时保留你熟悉的 PHP 语法。


什么是 TypePHP?

TypePHP 是一个 AOT(Ahead-Of-Time,提前编译)编译器,它把 PHP 源码翻译为 C++, 再编译为原生机器码。与字节码缓存或虚拟机不同,它不会在运行时解释 opcode, 而是直接生成在 CPU 上运行的原生二进制。

它保留熟悉的 PHP 语法,同时引入编译期类型信息,让编译器为你的性能热点生成快速、 静态类型的 C++ 代码,而其余代码仍运行在久经考验的 Zend 引擎上。

特性

  • 真正的 AOT 编译 —— PHP 先降级为 C++17,再编译为原生机器码。无解释器、 无 opcode 缓存、无 JIT 预热。
  • 三种构建模式 —— 同一份代码可编译为独立 bin 可执行文件、可加载的 PHP ext 扩展,或 lib 静态库。
  • 原生类型系统 —— intfloatbool 直接映射为 C++ 标量类型 (int64_tdoublebool),数值代码可获得数量级的性能提升。
  • 高精度数值 —— bigInt(GMP)、decimal(libmpdec)、bigFloat(MPFR), 零开销算术运算。
  • 强类型容器 —— std::arraystd::vectorstd::mapstd::ordered_map, 元素类型在编译期确定;最高比 PHP 数组快 10 倍,性能与 C++ std::vector 相当。
  • 通用方法(Universal Methods) —— 在原生类型上直接调用方法 ($s->upper()$arr->contains()$big->mul(2)),零运行时派发开销。
  • 混合 C++ / PHP 编程 —— 在性能关键内核中直接调用 C++ 函数(反之亦然)。
  • 编译期函数与关键词 —— any()refval()objval()expected()unexpected(),以及 toInt()toString()toArray() 等。
  • 编译期安全检查 —— #[Immutable] 只读契约和 #[ArrayDef] 数组结构元数据, 在编译期检查,零运行时开销。
  • 现代 PHP 支持 —— PHP 8.4 property hooks、非对称可见性、PHP 8.5 clone()-with 以及 (void) 丢弃表达式。
  • 跨平台与 WASM —— 面向 x86-64 和 ARM64 的 Linux、Windows、macOS 目标, 以及 WASI 0.2 和浏览器(Jco)输出。
  • Python 桥接 —— 为 Python 模块生成 IDE helper,并将 Python 脚本转换为 TypePHP。

为什么选择 TypePHP?

TypePHP AOT 字节码缓存(OPcache) JIT(PHP 8+)
编译目标 原生机器码 字节码 机器码(trace)
启动 / 预热 无(已编译完成) 每进程预热 JIT 预热
类型驱动优化 编译期、全程序 有限,基于 trace
独立可执行文件 支持 不支持 不支持
源码保护 编译为机器码 字节码(可还原) 字节码(可还原)
性能确定性

相较原生 PHP 的优势:

  • 接近原生的性能。 数值密集和容器密集的热点路径会编译为与 C++ 程序相同的机器码。 见下方基准测试
  • 源码保护。 源码被编译掉——交付物是原生二进制,而不是可读的 PHP 文件。
  • 零依赖部署。 二进制模式生成单个自包含可执行文件,无需 PHP 运行时即可运行。
  • 渐进式类型,真正带来收益。 只在性能关键处添加 use native_typesstd:: 容器和类型声明,其余保持普通 PHP。
  • 完整 PHP 生态互通。 扩展模式以标准 PHP 扩展形式加载到 php-fpm, 现有框架和工具链可继续使用。

前置要求

  • PHP 8.4 – 8.5,需包含 embed 模块(libphp.so
  • GCC 9+(或 Clang),支持 C++17
  • CMake 3.24+
  • 高精度数学库:GMPMPFRlibmpdec
# Ubuntu/Debian
sudo apt install libgmp-dev libmpfr-dev libmpdec-dev

# RHEL/CentOS/Fedora
sudo dnf install gmp-devel mpfr-devel libmpdec-devel

# Arch Linux
sudo pacman -S gmp mpfr mpdecimal

GMP 用于 bigInt,MPFR 用于 bigFloat,libmpdec 用于 decimal

预览版目前以 Linux 为主要开发平台(推荐 Ubuntu 22.04)。Windows 和 macOS 打包通过同一入口点支持。

安装

通过 Composer

composer require --dev swoole/typephp

然后编译你的项目:

vendor/bin/tpc.php project.yml

在 TypePHP 源码仓库中开发时,改用本地入口:

bin/tpc.php project.yml

构建 libphp.so

tpc 需要以 embed SAPI 构建的 PHP。如果 Linux 上缺少 libphp.sotpc.php 可以交互式下载 PHP 源码并自动构建。详见 自动构建 libphp.so

快速开始

创建 hello.php

<?php

function main(): void
{
    echo "Hello World!\n";
    var_dump(PHP_VERSION);
    var_dump(php_uname());
}

编译并运行:

bin/tpc.php hello.php
./hello

输出:

Hello World!
string(5) "8.4.x"
string(16) "Linux ..."

二进制模式需要全局 main() 函数。它可以声明为无参数,或 main(int $argc, array $argv) 以接收命令行参数,且必须返回 void

编译模式

TypePHP 支持三种构建模式,通过 -m / --mode 选择:

模式 参数 输出 需要 main() 典型用途
二进制 -m bin(默认) 可执行文件 CLI 工具、常驻服务、独立应用
扩展 -m ext .so / .dll php-fpm 上的 Web 应用、即插即用 PHP 扩展
-m lib 静态库 将编译后的代码嵌入其他项目
# 二进制(默认)
bin/tpc.php app.php -o myapp

# PHP 扩展
bin/tpc.php extension/ -m ext -o my_extension

# 静态库
bin/tpc.php lib/ -m lib -o mylib

详见编译模式

使用示例

1. 原生类型 —— 编译期数值加速

<?php
use native_types;

function fib(int $n): int
{
    if ($n == 1 || $n == 2) {
        return 1;
    }
    return fib($n - 1) + fib($n - 2);
}

function main(int $argc, array $argv): void
{
    $n = (int)$argv[1];
    $begin = microtime(true);
    echo fib($n) . "\n";
    echo "Time: " . (microtime(true) - $begin) . "\n";
}
bin/tpc.php fib.php -O3 -o fib
./fib 30

使用 use native_types 后,int 变量变为 C++ int64_t,算术运算直接编译为 CPU 指令,而不是 ZendVM 调用。

2. 高精度数值

<?php
declare(strict_types=1);
use native_types;

function main(): void
{
    // 54 位整数 —— 自动识别并存储为 bigInt
    $a = std::bigInt("123456789012345678901234567890123456789012345678901234");
    $b = std::bigInt("987654321098765432109876543210987654321098765432109876");

    echo $a->add($b)->toString() . "\n";   // 精确计算,不会溢出

    // 精确的十进制运算 —— 无二进制浮点误差
    $c = std::decimal("0.1")->add(std::decimal("0.2"));
    echo $c->toString() . "\n";            // "0.3"

    // 256 位浮点数
    $pi = std::bigFloat("3.14159265358979323846264338327950288419716939937510");
    echo $pi->mul(2)->toString() . "\n";
}

详见高精度类型原生类型

3. 强类型容器

<?php
use native_types;

function main(): void
{
    $vector = std::vector(Type::Int);

    $vector[] = 1;
    $vector[] = 2;
    $vector[] = 3;

    $sum = 0;
    foreach ($vector as $value) {
        $sum += $value;
    }

    echo $sum . "\n";       // 6
    echo $vector[1] . "\n"; // 2

    // 固定 key/value 类型的映射
    $map = std::ordered_map(Type::String, Type::Int);
    $map["a"] = 1;
    $map["b"] = 2;
}

详见 Std 容器

4. 通用方法

<?php

function main(): void
{
    $s = "hello world";
    echo $s->length() . "\n";       // strlen()
    echo $s->upper() . "\n";        // strtoupper()
    echo $s->substr(0, 5) . "\n";   // substr()

    $arr = [1, 3, 5, 7, 9];
    echo $arr->count() . "\n";      // count()
    var_dump($arr->contains(3));    // in_array()

    $big = std::bigInt("12345678901234567890");
    echo $big->mul(2)->toString() . "\n";
}

原生类型上的方法调用在编译期被解析为直接的 C/C++ 函数调用——没有虚表查找、 没有反射、没有运行时派发。详见通用方法

5. 混合 C++ / PHP

用 C++ 编写性能关键内核,并在 PHP 中调用:

// math.cpp
#include <phpx.h>

using namespace php;

var php_fast_sum(Int a, Int b) {
    return a + b;
}
<?php
// math.stub.php —— 声明 C++ 函数签名
function fast_sum(int $a, int $b): int;
<?php
function main(): void
{
    echo fast_sum(3, 4) . "\n";  // 7
}

详见混合 C++/PHP

基准测试

一个 10000×100000 的元素累加循环,对比 PHP 数组、TypePHP std::array 与原生 C++:

实现 耗时
PHP 数组(JIT) 67.6 秒
std::array(TypePHP AOT) 6.4 秒
C++ std::vector 6.2 秒

std::array 比 PHP 数组快约 10 倍,性能与手写 C++ 完全一致。 完整基准测试见 Std 容器

命令行

bin/tpc.php <file|dir|project.yml> [options] [-- program-args...]

常用示例:

# 编译单个文件
bin/tpc.php app.php

# 优化并运行,`--` 后的参数传给生成的程序
bin/tpc.php app.php -O3 -r -- --flag value

# 编译 project.yml 定义的项目
bin/tpc.php project.yml -O2 -j 8

# 生成 PHP 扩展
bin/tpc.php extension/ -m ext -o my_extension

# 只生成 C++(跳过编译与链接)
bin/tpc.php app.php --dry --build-dir /tmp/typephp-build

# 编译为 WASI 0.2
bin/tpc.php --wasm app.php

# 编译为浏览器目标(需要 jco)
bin/tpc.php --wasm=browser app.php

主要选项:

选项 说明
-O <0-3> 优化级别(默认 0
-d, --debug 调试构建,带符号和源码跟踪
-o, --output <file> 输出文件名
-m, --mode <bin|lib|ext> 构建模式(默认 bin
-r, --run 构建成功后运行
-j, --job <num> 并行编译任务数(默认 4
--build-dir <dir> 生成 C++ 与中间产物的目录
--dry 只生成 C++,跳过编译与链接
--php-version <8.4|8.5> 接受的 PHP 语法版本
--cxx-std <ver> C++ 标准(如 c++17c++20
--march <arch> 目标指令集(如 native
--lto 启用链接时优化
--sanitize <type> 启用 sanitizer(如 address

运行 bin/tpc.php --help 查看权威的最新参数列表。详见 编译器命令行,包括 Bash 补全:

source <(./tpc --generate-completion=bash)

Python 桥接

TypePHP 内置一个 Python 工具子模块,复用 tpc 入口:

# 为 Python 模块生成 IDE helper
./tpc --gen-python-helper math
./tpc --gen-python-helper numpy --output-dir .ide-helper

# 将 Python 脚本转换为 TypePHP
./tpc --convert-python-to-php script.py > script.php

详见 Python 工具子模块

文档

授权协议

TypePHP 采用 GNU General Public License v3.0 授权。

社区