Skip to content

perf(tui): 合并统计刷新并减少重复快照写入 - #44

Closed
aiev wants to merge 2 commits into
Hotakus:masterfrom
aiev:perf/coalesce-session-stats
Closed

aiev wants to merge 2 commits into
Hotakus:masterfrom
aiev:perf/coalesce-session-stats

Conversation

@aiev

@aiev aiev commented Oct 8, 2026

Copy link
Copy Markdown
Contributor

背景

基于当前 master(6d93e072b76be983394c4e2f82803803697e1bb4,1.7.5)。流式 token 更新会反复扫描历史 parts、重新估算未变化的大段工具输出,并保存相同的分布快照。已有的 part debounce 仍同时递增立即刷新信号,未能合并实际的重计算;V2 全局事件也需要按当前查看的会话过滤。

另外,旧 dist_snapshot 不记录所属会话,切换到尚未加载消息的会话时可能显示前一个会话的分布。

改动

  1. 合并重计算:以 100ms 有界窗口合并分布更新,而不是不断推迟的 trailing debounce;保留轻量统计的响应式依赖,包括存在 session 聚合值时的嵌套 output/reasoning 更新。模型定价索引独立 memo,避免随每次 token 更新重复组装。
  2. 复用文本估算:按语义输入缓存贡献,不依赖对象引用不变;同一对象内的工具输入、输出、状态、文本标记及技能变化仍会失效。只保留当前加载的消息,切换查看会话时清空;分布与本回合 step 统计共用一次 part 遍历。
  3. 保留 V2 事件归属:桥接 tool/step/execution 事件,拒绝其他会话及归属不明的全局事件;保留兼容宿主的旧事件名。适配层透传宿主实际提供的 session tokens/cost;不可用时仍走消息累加兜底。
  4. 减少并隔离快照写入:快照改为 { version: 1, sessionID, dist },只恢复当前会话且字段有效的值。250ms 合并、逐字段比较、异步串行保存,慢存储最多保留一个最新等待值;切换与卸载时 flush,失败不影响面板。无归属的旧派生缓存会重新计算,不修改真实消息或历史记录。
  5. 补齐生命周期清理:卸载取消重计算、事件监听和 storage-ready 等待;延迟恢复不覆盖已经有效的实时分布。
  6. 新增回归测试、CI 测试步骤、可复现的 Linux/PTY 比较脚本及脱敏证据。保持双入口架构、余额凭据/轮询和包版本不变;不包含 npm 发布。

验证

  • npm test:21 项通过,包括原有余额/凭据测试,以及语义缓存、原地修改、迟到数据、回合边界、快照归属、持续流不饥饿、异步串行保存、等待队列去重及存储失败。
  • npm run typecheck、npm run build、npm pack --dry-run、git diff --check 均通过。
  • OpenCode 2.0.22 真实 TUI:交替顺序运行三轮/实现,共六次;84 项断言通过。覆盖初始/最终精确计数、命中率、成本、模型、skills、子会话空视图/迟到数据/返回父会话、旧待执行任务隔离、无事件的嵌套 Solid-store 更新及卸载清理。
  • 最终构建另做正常启动 smoke:保留全部七个已配置的 CLI 插件指令;该历史会话的 281 条 subagent 记录前后完全一致,shell manifest 字节一致;未提交 prompt 或清理历史。

性能测量

比较未修改的已安装 1.7.5 bundle与最终构建。fixture 挂载实际面板与适配层,使用 host memory storage、128 条合成消息,每条工具输出 17,408 字符;当前消息进行 64 次 token 更新(间隔 20ms,结束后等待 450ms)。不挂载余额轮询/命令根,不读取余额凭据或发起模型请求。

同一 64 次更新阶段 1.7.5 本分支
整个临时 TUI 的 CPU 耗时,三次(ms) 1,967 / 2,037 / 2,065 229 / 192 / 243
CPU 耗时均值(ms) 2,023.0 221.3
历史输出文本 getter 访问次数(每次试验) 8,256 1,664
snapshot update 调用次数(每次试验) 64 5

该合成、大输出、活跃更新阶段的整份客户端 CPU 耗时减少 89.1%;输出 getter 访问减少 79.8%,snapshot update 调用减少 92.2%。新旧初始及最终分布完全一致。其他会话的八个 legacy 回调由九次无效扫描/相同快照更新降至零;当前会话数据未变化时也不再保存相同快照。

测量边界

  • CPU 指标是相同工作量内 process.cpuUsage() 的 user + system CPU-ms,不是插件独占 CPU,也不是常态 CPU 使用率。
  • getter/update 计数是内存访问与调用次数,不是物理磁盘读写次数。
  • 比较时 inline CLI 配置仅加载 fixture;这不是完整插件列表的端到端性能比较。后台服务及其他 TUI 保持运行,三轮数据仍可能受共享环境影响。
  • 不声称所有真实会话都快 89.1%,也不声称 idle CPU 或 RAM 改善。 缓存仅保留当前加载消息,但仍有相应内存成本;大工具输出在刷新时仍会归一化,不是增量磁盘 I/O。
  • 真实 TUI 验证针对 V2;V1 兼容路径保留,但未在 1.x 宿主做同等实测。

证据与复现

  • 详细报告
  • 脱敏测量数据及 SHA-256
  • scripts/benchmark-visual-cache.py + scripts/fixtures/visual-cache.mjs:无需旁边的其他插件仓库;检查会话已存在、拒绝覆盖已有证据目录、验证实际加载 bundle 的 profile,并确认全局 CLI 配置与 bundle 未改变。复现命令见报告。

最终评审加强了异步保存与卸载处理,已重新测量最终 bundle;此前开发阶段的约 90% 数据不作为本 PR 的最终证据。

@aiev aiev closed this Oct 10, 2026
@aiev
aiev deleted the perf/coalesce-session-stats branch October 10, 2026 02:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant