【免费下载链接】Pi-Bolt
⚡ Pi, the coding agent, compiled ahead of time to one native executable. 10× faster to start, 7× less CPU and 4.5× less memory than Pi on Node. Linux, macOS, Windows, ARM64 and Android (Termux).
Pi-Bolt 是把 AI 编程智能体 Pi提前编译(AOT 编译)成单个原生可执行文件的项目:运行时无需 Node.js、无需 Bun、无需 JIT,启动比 Node 快 10 倍、CPU 少 7 倍、内存少 4.5 倍。本文将带你完整走一遍 Pi-Bolt 的工作原理——从 AOT 编译器如何"看不运行就能编译",到预建静态堆(static heap)与代码镜像(code image)如何在启动时直接从文件映射,让你彻底理解这个 41 毫秒启动的智能体背后发生了什么。
1. Pi-Bolt 是什么:一个文件,三种优势
普通 Pi 跑在 Node 或 Bun 上,每次启动都要装解释器、解析代码、预热 JIT。Pi-Bolt 的思路相反:把一切工作都提前做完,打包进一个可执行文件。
| 指标(Linux x86-64) | Pi on Node 24 | Pi-Bolt | 提升 |
|---|---|---|---|
| 就绪可输入时间 | 423 ms | 41 ms | ⚡ 10× 更快 |
| 工具调用写 400 KB 文件 | 143.7 s | 1.2 s | 120× 更快 |
| 长回答流式输出 CPU | 18.6 s | 2.3 s | 8× 更少 |
| 40 轮会话后内存 | 521 MB | 117 MB | 4.5× 更少 |
你仍然使用熟悉的 Pi:同样的命令、会话、配置、模型提供商和扩展,只是快了很多。
2. 可执行文件解剖:一个文件里的五层结构
理解 Pi-Bolt 工作原理的第一步,是知道这个可执行文件里到底装了什么。它在标准 Bun 单文件可执行文件之外,追加了两个页对齐的区段,可以直接从文件映射进内存:
┌──────────────────────────────┐ │ Bun 运行时(含 AOT 引擎) │ 静态链接 ├──────────────────────────────┤ │ 打包好的 Pi 程序 │ 模块字节码(可选) ├──────────────────────────────┤ │ 静态堆(static heap) │ 模块加载求值后的 JS 堆快照 ├──────────────────────────────┤ │ 代码镜像(code image) │ 所有函数、正则、元数据的机器码 ├──────────────────────────────┤ │ 尾部(trailer) │ 偏移量、引擎戳、CPU 特性清单 └──────────────────────────────┘关键点:静态堆和代码镜像都按页对齐,启动时内核可以把它们按 copy-on-write 方式直接从文件映射——读过的页共享页缓存,内存紧张时还能被回收。详细定义见 docs/ARCHITECTURE.md。
3. 构建流水线:从源码到可执行文件的 5 步
构建由 scripts/build-pi.sh 驱动,核心命令是bun build --compile --bytecode加一组关键开关。五个步骤依次是:
- 打包(Bundle):Bun 解析 Pi 的模块图(
dist/bun/cli.js及两个 worker 入口),转译并链接; - 字节码:每个模块和函数编译成 JavaScriptCore 字节码,模块图预链接;
- 求值入堆:在按快照布局的 VM 中加载并求值 Pi 的模块,序列化出一堆"指针全部可重定位到固定地址"的数据——这就是预建静态堆;
- AOT 编译:前文编译器把每个函数的字节码变成机器码,链接成一张完整的代码镜像;
- 追加(Append):把静态堆、代码镜像和尾部追加进可执行文件。
几个最关键的构建参数及其作用:
| 参数 | 效果 |
|---|---|
BUN_STATIC_HEAP=1 | 生成静态堆 |
BUN_AOT=1 | 所有函数提前编译进代码镜像 |
BUN_AOT_JIT=0 | 标记为"JIT 关闭"运行(默认构建) |
BUN_JSC_omitBytecodeFromStaticHeap=1 | 堆中不留字节码——只从机器码运行,省内存并支持跨函数内联 |
BUN_JSC_useAotLoopSplitting=1 | 给循环生成"快速副本"(见下节) |
--bytecode-order=profiles/.../bytecode.order | 按训练会话的实际使用顺序排布代码和堆 |
BUN_JSC_aotRegExpsPath=profiles/.../regexps.txt | 把运行时从字符串构建的正则也提前编译 |
4. 核心难题:AOT 编译器如何"不看运行轨迹"就编译
JIT 靠观察代码运行时学到类型信息再优化;AOT 编译器没有这个特权,它只能靠证明。Pi-Bolt 的 AOT 编译器(源自 oven-sh 的 WebKit 分支,经 patches/webkit.patch 移植了 x86-64 后端,patches/bun.patch 实现了可执行文件格式)这样做到:
- 全程序类型推断:局部变量类型、永远不变指向同一函数的模块绑定、常量;
- 守卫(guard):对"无法证明但假设成立"的条件(如值是 int32、对象形状)插入检查,失败时走编译在内的通用路径——没有"去优化",慢路径本身就是机器码的一部分;
- 桩(stubs):通用路径共享的机器码例程(属性访问、调用、未知类型算术),让慢路径只付一次函数调用的代价;
- 内联缓存(inline cache):属性访问运行时填充,多态时做内联检查;
- 内建函数 intrinsic:
Math.*、charCodeAt、push/pop、Map/Set的get/has/set/add; - 跨函数内联:函数声明、永不重新赋值的模块常量函数、全程序只定义一次的方法,都可以被内联;
- 循环分裂(loop splitting):循环生成一份无慢路径的"快速副本",检查失败才回退到通用副本——字符串扫描和数值运算因此快数倍;
- 正则表达式:由 JavaScriptCore 的 Yarr 引擎编译进同一张镜像,覆盖字面量和训练配置记录过的运行时正则。
完整机制讲解见 docs/ARCHITECTURE.md。
5. 训练配置(Training Profile):教会构建"从哪开始"
Pi-Bolt 每版 Pi 配一份训练配置(如 profiles/pi-1.4.0/),由 scripts/lib/train_session.py 跑两段脚本化交互会话录制而成,只有两个文件:
| 文件 | 内容 | 用途 |
|---|---|---|
| bytecode.order | 函数首次执行的顺序 | 代码和堆按此排布,启动时触碰的内存页最少 |
| regexps.txt | 运行时从字符串构建的正则 | 像字面量一样提前编译 |
注意一个实用细节:没被记录的正则不会被编译,默认构建下落入解释器,慢 10 倍以上。scripts/lib/training.md 里定义了会触发所有 Markdown 高亮和工具调用的"训练文案";新增高亮语言时要补录。构建后用 bench/aot_coverage.py 可以列出哪些代码仍在编译产物之外运行。
6. 启动时刻:41 毫秒里发生了什么
可执行文件启动时的动作简单到令人惊讶:
- 校验尾部:引擎戳(engine stamp)必须完全一致、CPU 必须支持编译时的指令集特性、堆与代码期望的地址空间可用;
- 映射静态堆:在固定地址(x86-64 上为
0x200000000000)以 copy-on-write 方式直接从文件映射,结构区落在其后 4 GB 处——正是代码预期的位置; - 映射代码镜像:按可执行方式映射并注册进 VM,堆中函数直接指向机器码;
- 运行:Pi 的模块和
main()就在堆里,没有解析、没有编译——唯一每次启动才运行的是模块顶层代码和node:*模块,且它们也是编译态。
任何一步校验失败(如ulimit -v太紧),程序只打印一行提示,退回字节码运行:结果正确,只是启动慢一点。详见 docs/TROUBLESHOOTING.md。
内存上还有三重节省:代码和静态堆是文件支持页(可共享、可被内核丢弃);JIT 关闭意味着没有编译器线程、JIT 代码缓存和 profile 数据;堆中没有字节码。
7. JIT 关闭 vs JIT 开启:两个构建怎么选
| JIT 关闭(默认) | JIT 开启(--jit on) | |
|---|---|---|
| Pi 自身代码 | AOT 机器码 | AOT 机器码(不再升级) |
运行时加载的代码(插件、eval) | 解释执行 | 解释 → 基线 JIT → DFG → FTL 逐级预热 |
| 内存 | 最低 | JIT 一旦编译任何东西就会更高 |
| 适合 | 插件已编译进二进制的场景 | 重度使用运行时插件 |
经验法则:日常插件用pi-bolt compile编译进去(见 docs/PLUGINS.md),选默认构建;插件多且重就选 JIT 构建。
8. 一套编译器,五大平台:移植都做了什么
上游 AOT 编译器只覆盖 ARM64,Pi-Bolt 把其余平台逐一补齐:
- x86-64:全新后端,包括适配小寄存器集的桩约定、全部桩家族移植、
u/v标志正则的代理对慢路径、double→int32 内联截断; - macOS(Apple silicon):程序存在 Mach-O 的
__BUN段中;整个可执行文件做 ad-hoc 签名后代码镜像可直接按可执行方式映射(无需MAP_JIT);pi是个小启动器,用posix_spawn让真正的pi-bin以链接时的固定地址运行(静态堆里有指向可执行文件自身的指针);构建时还用F_RDADVISE批量预读热页,冷启动从约 170 ms 降到约 65 ms; - Linux ARM64:静态区改在 64 GB 处以适配 512 GB 地址空间的内核(Android、树莓派);堆与代码镜像按 64 KB 页排布,4/16/64 KB 页内核一个二进制全兼容;用
baseline(纯 ARMv8.0)特性保证树莓派 3 到 Graviton 4 同一构建通吃; - Android(Termux):安装器把可执行文件的加载器路径改写为 Termux 的 glibc,运行时对 Android 拒绝的系统调用自行降级。
9. 动手验证:构建并亲眼确认流水线
想验证整个工作原理,流程只有三步(约 1 分钟出结果):
git clone https://gitcode.com/gh_mirrors/pi/Pi-Bolt && cd Pi-Bolt scripts/fetch-runtime.sh # 下载发布版运行时 scripts/prepare-pi.sh # 构建本仓库中的 Pi scripts/build-pi.sh # 产出 out/pi-bolt/pi构建脚本会自动检查结果必须报告image registered: true——证明它跑的是编译好的代码而非解释器。完整构建指南见 docs/BUILDING.md。
可靠性方面同样讲究:引擎正确性由 tests/aot/run.sh 用三种编译模式对照原版 Bun 验证,再加 32,000 个差分模糊测试程序;对照 JavaScriptCore 官方JSTests/stress套件,4,786 个可运行测试中 4,780 个行为一致。
构建完成后,你的 Pi-Bolt 就是下面这个样子:
10. 已知局限(保持清醒的期望)
- 覆盖平台:Linux x86-64/ARM64(含 Termux)、macOS Apple silicon、Windows x64;Windows on ARM64 走 x64 模拟;
- 运行时加载的代码不会被 AOT 编译,默认构建下解释执行——编译插件进去或用 JIT 构建;
- 没有类型反馈:AOT 只能用"能证明的",类型可预测的代码才能走满快速路径;
- 每个可执行文件只对应一个 Pi 版本 + 一个引擎,启动时校验引擎戳。
11. 总结:把"慢"全部搬到构建时
Pi-Bolt 工作原理的本质可以浓缩成一句话:把解析、编译、模块加载、正则构建这些启动时的开销,全部用 AOT 编译 + 预建静态堆 + 代码镜像搬到构建时,启动只剩三次"校验 + 映射 + 运行"。训练配置(bytecode.order/regexps.txt)则进一步告诉构建"从哪开始、编译哪些正则",让 41 毫秒就绪和 117 MB 内存成为可能。想深入每一处细节,docs/ARCHITECTURE.md 与 docs/BUILDING.md 是最好的两站。
【免费下载链接】Pi-Bolt
⚡ Pi, the coding agent, compiled ahead of time to one native executable. 10× faster to start, 7× less CPU and 4.5× less memory than Pi on Node. Linux, macOS, Windows, ARM64 and Android (Termux).
相关推荐
如何优雅处理Sidekiq-status过期时间:Redis存储优化策略:10个关键技巧提升作业监控效率
如何优雅处理Sidekiq status过期时间:Redis存储优化策略:10个关键技巧提升作业监控效率 Sidekiq status过期时间配置是每个使用Si
后端任务调度RR构建与编译流程:从源码到可启动镜像的完整指南
RR构建与编译流程:从源码到可启动镜像的完整指南 本文详细介绍了RR项目的完整构建流程,从环境准备、依赖管理到镜像打包与分区处理的完整技术实现。文章系统解析了构
固件系统编程LunaTV 配置订阅首次同步:5 步把播放源配好
LunaTV 配置订阅首次同步:5 步把播放源配好 这篇文章写给刚部署完 LunaTV、还不知道播放源怎么来的站长。它只讲一件事:用配置订阅功能,把别人整理好的
前端音视频视频
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考