omp packages

@aiwayds/pi-turbo0.2.1

pi-turbo — optimized pi launcher with parallel extension loading and footer caching

aiwayds Published 7 days ago MIT ~193 downloads/mo

Untested on omp

This is a pi package. No one has reported whether it works on omp yet. If you try it, add your result below.

Did it work for you?

Result

One report per person. A new report replaces your old one.

Reports 0

No reports yet.

Readme

English | 中文

pi-turbo

pi 的性能加速包装器 — 两个运行时 monkey-patch,对 pi 本身零修改。

  • 启动加速:并行加载扩展(冷启动提速 33%)
  • 运行时优化:Footer 渲染缓存(消除长对话中按 Enter 的卡顿)

为什么做 pi-turbo

这个仓库源于日常使用 pi 的两个痛点:

  1. 扩展加载又慢又串行。 pi 逐个加载扩展,不支持异步 — 每次冷启动都要盯着空白终端等上几秒。pi-turbo 先为每个扩展记录耗时画像,之后把 I/O 密集扩展(如 MCP 握手)放到后台加载,其余扩展照常加载,让 I/O 等待与 CPU 工作重叠(A/B 测试约提速 30%)。
  2. 长会话卡得像 hang 住。 消息超过约 100 条后,按回车发送会出现延迟,而且消息越多越卡。一个重要原因:Footer 每帧渲染都会重新扫描全部会话条目。pi-turbo 按条目数缓存这些结果(getEntries() / getContextUsage()),后续渲染直接命中 O(1) 缓存,不再重复 O(n) 扫描 — 削掉了随会话增长而放大的每帧渲染开销。

它解决什么问题(Problems it solves)

1. 启动慢(扩展加载)

症状:pi 启动需要 4-5 秒。你只能盯着空白终端,等扩展一个一个加载完。

原因:pi 串行加载所有扩展。部分扩展(如 MCP 握手)是 I/O 密集型的,CPU 全程空转等待。

方案:pi-turbo 对 DefaultResourceLoader.loadFinalExtensionSet 打补丁:

  1. 画像(首次运行):逐个加载扩展,记录每个扩展的耗时(EMA)
  2. 优化(后续运行):识别 I/O 密集扩展(EMA > 1000ms,如 MCP 握手),放入后台加载,CPU 密集扩展继续串行加载
  3. 重叠:I/O 等待与 CPU 工作并行执行 → 总耗时 = max(后台, 串行)
模式 扩展加载耗时 提速
串行(pi 默认) ~4660ms —
定向并行 ~3125ms 33%

2. Enter 键卡顿(Footer O(n) 扫描)

症状:对话超过 100 条消息后,按 Enter 有明显延迟。对话越长,卡顿越严重。

原因:pi 的 Footer 每次渲染都重新扫描全部会话条目(O(n))来计算 token 用量统计,加上 getContextUsage() 要做树遍历和对每条消息执行 JSON.stringify。

方案:pi-turbo 对 SessionManager.getEntries() 和 AgentSession.getContextUsage() 加智能缓存:

  • getEntries():返回缓存数组,仅在追加新条目时失效(O(1) vs O(n) 过滤 + 新数组分配)
  • getContextUsage():按条目数缓存,避免重复树遍历和 token 估算(O(1) vs O(n) + O(内容大小))

对 pi 的影响(Impact on pi)

零。 pi-turbo 不碰 pi 的源码、node_modules 或配置文件。

  • 所有补丁都是原型方法上的运行时 monkey-patch
  • 每个补丁都包在 try-catch 里 — 任何错误都回退到 pi 的原始行为
  • kill-switch 可以独立禁用任何优化
  • 卸载后不留痕迹;pi 和之前完全一样

唯一可观察到的区别:pi 启动更快,Footer 不再卡顿。

证据(Evidence)

启动:A/B 基准测试

20 个扩展,每种模式各跑 3 次:

串行基线 (PI_TURBO_SERIAL=1):5140ms, 5000ms, 9251ms

并行(默认):

⚡ pi-turbo: 20 exts in 6507ms (serial ~9432ms, saved 31%, 1 chunk)
⚡ pi-turbo: 20 exts in 8387ms (serial ~11489ms, saved 27%, 1 chunk)
⚡ pi-turbo: 20 exts in 9796ms (serial ~13797ms, saved 29%, 1 chunk)

注:"saved %" 按每次运行计算:(估算串行时间 - 实际并行时间) / 估算串行时间。估算串行时间 = 各扩展 EMA 画像之和。绝对时间随系统负载波动;比率才是稳定指标。

启动:EMA 画像

pi-tb --status 输出示例:

extensions/index.ts    2527ms  ← lean-ctx MCP 桥接(I/O 密集)
dist/index.js           309ms
其余 18 个扩展          <100ms

I/O 密集扩展(2527ms)放入后台块,与 CPU 密集扩展的串行加载并行执行。I/O 等待与 CPU 工作重叠,总耗时取决于两者中较慢的那个,而非两者之和。

Footer:pi 源码中的 O(n) 扫描

代码级证据(无法通过基准测试量化,以下为 pi 源码路径):

  • footer.js:80 — 每帧渲染调用 sessionManager.getEntries()
  • session-manager.js:980 — getEntries() 执行 this.fileEntries.filter(e => e.type !== "session") — 每次调用 O(n) 过滤 + 新数组分配
  • agent-session.js:2534 — getContextUsage() 执行 getBranch() O(n) 树遍历 + estimateContextTokens 对所有消息 JSON.stringify

fileEntries 只追加不删除,n 随对话增长。100+ 条消息后,每次按 Enter 触发 O(n) 扫描 + O(内容大小) 序列化 → 可感知卡顿。

修复方式:WeakMap 缓存,以 fileEntries.length 为键(利用只追加不变量)。缓存命中 = O(1)。缓存未命中(新条目追加)= 一次 O(n),之后重新缓存。

安装(Install)

npm i -g @aiwayds/pi-turbo

或从源码安装:

git clone https://github.com/fan56/pi-turbo.git
cd pi-turbo
./install.sh

从 pi-opt 升级

如果你之前安装过 pi-opt,直接重新运行 ./install.sh 即可。它会:

  • 移除旧的 pi-opt 全局命令
  • 安装新的 pi-tb 命令
  • 将时序数据从 ~/.pi-opt/ 迁移到 ~/.pi-turbo/

使用(Usage)

pi-tb                          # 启动 pi,启用所有优化
pi-tb --status                 # 查看各扩展的时序统计
PI_TURBO_SERIAL=1 pi-tb        # 禁用启动优化(A/B 基线对比)
PI_TURBO_NO_FOOTER=1 pi-tb     # 仅禁用 Footer 缓存

启动日志(Startup logging)

pi-turbo 会往 stderr 输出启动信息日志。可通过 PI_TURBO_STATS 控制:

  • PI_TURBO_STATS=0 — 关闭所有启动信息性日志(错误与回退日志仍会显示)。默认开启一行启动摘要。
  • PI_TURBO_STATS=1 — 额外显示 chunk 细节等详细统计。
  • PI_TURBO_SERIAL=1 — 禁用并行加载(A/B 基线测试用)。

卸载(Uninstall)

./uninstall.sh

工作原理(How it works)

pi-turbo 是一个轻量包装器,在运行时打两个 monkey-patch:

  1. 扩展加载器 — 替换 DefaultResourceLoader.prototype.loadFinalExtensionSet,使用 EMA 时序画像识别 I/O 密集扩展并行加载。

  2. Footer 渲染缓存 — 包装 SessionManager.prototype.getEntries 和 AgentSession.prototype.getContextUsage,以条目数为键缓存结果,消除每帧渲染的 O(n) 扫描。

两个补丁都是 fail-safe 的:任何错误都回退到 pi 的原始行为。

文件(Files)

  • bin/pi-tb.js — CLI 入口
  • src/patch.js — monkey-patch 编排器
  • src/footer-patch.js — Footer 渲染缓存
  • src/targeted-loader.js — 定向并行加载算法
  • src/timing.js — EMA 时序记录器
  • src/config.js — 路径和常量
  • ~/.pi-turbo/per-ext-timings.json — 各扩展时序数据(自动创建)

环境变量(Environment variables)

变量 默认值 作用
PI_TURBO_SERIAL=1 — kill-switch:强制串行加载扩展
PI_TURBO_OFF=1 — 完全跳过所有补丁
PI_TURBO_CHUNK 4 每个并行块包含的扩展数
PI_TURBO_DEBUG=1 — 输出详细加载日志
PI_TURBO_PROFILE=1 — 强制重新画像(忽略现有 EMA 数据)
PI_TURBO_NO_FOOTER=1 — 仅禁用 Footer 缓存
PI_TURBO_STATS 默认开启摘要 =0 关闭所有启动信息性日志(错误与回退日志仍会显示);=1 额外显示详细统计

系统要求(Requirements)

  • Node.js >= 22.19.0
  • pi (@earendil-works/pi-coding-agent) >= 0.50.0