Files
goodbuddy/docs/review/performance-phase-1-report-2026-10-04.md
T

7.1 KiB
Raw Blame History

桌面端性能改造(第一期,参照 VS Code 架构)结项报告

  • 时间: 2026-10-02 至 2026-10-04
  • 范围: Desktop 的 Electron Main、Preload、Renderer 及其后台线程。远程主机(Agent、SSH、远程 Runtime)的稳定性和性能不在本期范围,下一期单独审查。
  • 结论: 本期计划内的工作已完成。用户日常能感受到的卡顿(打字、流式输出、切换会话、滚动、启动、写库)都已测量并修复。剩下的工作是架构上的长期项(存储接口异步化、独立数据进程),风险高,已经写明理由,留到后续单独立项。
  • 相关文档:
    • 性能原则和评审清单:docs/architecture/performance-principles.md
    • 逐项测量记录:docs/roadmap/product-performance-experience-improvement-plan.md 第 7 节(PERF-11 至 PERF-17)

1. 结果

1.1 模拟低端机(Renderer CPU 降速 4 倍)

场景 改造前 改造后
有 300 个会话时打字,按键延迟 p95 最高 4 秒 约 10–35 ms
流式输出时打字,按键延迟 p95 最高 9.6 秒 约 30–60 ms
流式输出期间卡住界面的总时长 16–21 秒 约 0.3–3 秒
切回刚看过的会话,点击延迟 p95 约 530 ms 约 110–140 ms
打开 2,000 条消息的会话 约 1.1–1.8 秒 约 0.27 秒

1.2 标准机

  • npm run perf:check 的 60 项阈值全部通过。
  • 流式输出、流式输出时打字,超过 50 ms 的长任务均为 0。
  • 改造前,流式输出 40 KB 回答时约 47% 掉帧,帧间隔 p95 83 ms。

1.3 Main 进程

Main 卡顿的数据来自真实数据,以及 5 万个文本块的知识库。

场景 改造前 改造后
5 万个文本块的知识库混合检索 490 ms 19 ms(移到只读 worker)
读取会话列表 25 ms 0.8 ms
活动记录:启动读取 14.2 MB,198 ms 114 KB,0.6 ms
活动记录:保存一条变化 114 ms 6.9 ms
导入大 PDF 0.5–0.7 s 约 16 ms(移到解析 worker)
单次写库(真实数据) 2.2–2.6 ms 0.1–0.3 ms
写入期间偶发卡顿(真实数据) 最长 346 ms,超过 50 ms 共 37 次 最长 34 ms,0 次

1.4 启动

真实数据:2.4 GB 数据库,175 万条任务事件。

指标 改造前 改造后
启动到输入框可用 3.70 s 1.36 s
侧栏出现会话 4.08 s 1.75 s
启动期间 Main 最长阻塞 2.5–2.8 s 约 0.25 s
空配置启动 1,044 ms 962 ms

2. 做了什么

按性能原则 P1–P10 归类,提交号见计划文档。

原则 改动
P1 Main 只做调度 知识检索、Story Graph、会话列表、会话搜索、活动记录分页和汇总放到只读 worker;文档解析、分块、哈希放到解析 worker;WAL checkpoint 放到后台线程;远程事件按检查点批量写库;高频本地写入使用 synchronous = NORMAL;启动恢复改为按索引读取(schema 58)
P2 状态局部订阅 流式缓冲、输入草稿、会话、任务和产物、活动记录、弹出层都改为独立 store;拆出 Composer、侧栏和隐藏路由并加 memo;切换会话只渲染一遍;App.tsx 从 11,246 行降到约 7,900 行,lint 设了上限
P3 高频数据按帧合并 流式文本按帧合并;终端输出在 Main 端按 8 ms 合并,界面每帧最多写一次;自动滚动每帧最多一次
P4 只传变化部分 活动记录改为增量保存和分页,统计由 Main 汇总,覆盖全部记录;Markdown 只重新解析变化的段落,并缓存解析结果
P5 工作量和可见内容成正比 消息时间线、会话侧栏、笔记、文件树、知识库文档表格都只渲染可见部分
P6 启动只做首屏需要的工作 本地工具环境改为后台初始化;Canvas、终端、SSH、OpenCode SDK 等模块改为用到时再加载;启动恢复改为按索引读取
P7 先测量,再修改 新增 perf:app(支持模拟低端机、内存、CPU 剖析)、perf:main、perf:knowledge、perf:document-parse、perf:startup(含 real 真实数据变体)、perf:write(真实数据回放)
P8 正确性优先于速度 分段渲染与整篇渲染对照测试,含随机语料;活动记录与改造前的整份列表逻辑逐步对照;数据库写入顺序和持久性边界有专门测试
P9 用工具守住规则 lint 规则:主进程禁止同步文件 API、限制 DatabaseSync 的使用范围、组件不得直接订阅 IPC、App.tsx 行数上限;perf:check 阈值
P10 体验不倒退 修复了 8 处体验倒退:回到底部的平滑动画、滚出可见区后丢失状态、跨消息选择文本、侧栏插入时跳动、终端回显、远程流式输出一顿一顿、复制时缺内容、锚定冲突

3. 有意不做的部分

项目 理由
存储接口全部异步化,新增独立数据进程(PERF-15、16 的剩余部分) 约 500 处同步调用,并且要保证“先写后读”的顺序,风险高。最重的读已经移出 Main,写入已降到每次 0.1–0.3 ms,收益已经不大
Markdown 解析放到后台线程 需要重写渲染流程。标准机上流式输出已经不卡,只有低端机上的长回答还有余量
窗口提前加载,接口请求排队等待 可省 200–300 ms,但要改动所有接口的注册顺序和首次运行流程
会话队列移出 App 和发送、恢���、中断联系太紧,拆出来的风险大于收益
性能阈值接入 CI 仓库目前没有 CI 配置

4. 已知问题和下一步

4.1 本期遗留

  • 打开最大的会话要等约 170 ms。 这个会话有 407 条消息、42 MB 附加数据。读取在 worker 上,不卡界面,但切换时要等。根因是附加数据冗余:

    • 子任务过程记录约 207 MB,主要是 read、bash 等工具的完整输出;
    • 旧的 tools 和新的 blocks 重复保存,约 65 MB;
    • 旧数据里有约 4 MB 内嵌图片。

    建议去重,并把工具输出改为按需加载,单独立项。

  • 持久性的变化。 高频本地写入改为 synchronous = NORMAL:断电时最多丢失最近一段运行事件和会话保存,应用崩溃时不丢。远程事件、通道投递、任务状态仍然每次落盘。

  • 没有在真实低配 Windows 机器上测过,也没有用同一标准实测 VS Code 作为对照。

  • 全量测试中 2 个监督者相关测试失败,在本期之前就已失败,属于另一项正在进行的工作。

4.2 远程主机(下一期)

本期涉及远程路径的改动只有 3 处:

  • d859cbf:远程事件按检查点批量写库;
  • 805acc3:远程流式合并间隔从 50 ms 改为 16 ms;
  • 0dd4d1d:远程事件仍然每次落盘,未降级。

用户报告的 Agent refused the stable controller generation resume 和 Runtime stopped before the prompt reached a terminal state 两个错误,还需要在下一期确认和这些改动有没有关系。确认方式:在改动前后的版本上复现,对照远程事件写入和确认(ACK)的顺序。