问题概述
src/commands/artifacts/scanner.ts 每发现一个 artifact tool_use,都会调用 findToolResult(messages, toolUseId) 从会话开头重新扫描全部消息。若会话有 N 条消息和 A 个 artifact,复杂度为 O(A × N);artifact 数量随会话增长时会退化为 O(N²)。
这会直接影响长会话打开 /artifacts 列表的响应时间。
环境
- 代码版本:
3bb6b5746238c418138eb96d57765d79012edd96
- Bun:
1.3.13
- 系统:
Linux 5.15.0-186-generic x86_64
对比方案
候选实现保留首个 artifact 的直接查找路径;检测到第 2 个 artifact 后,仅一次遍历用户消息,为 tool_result 建立 first-result-wins 的 Map,后续按 tool_use_id 做 O(1) 查找。结果顺序、重复 ID、result 先于 use、数组 content、error 和 unmatched 行为均保持不变。
基准方法
- 每个场景先做 60 对交替预热。
- 3 个独立 trial;每个 trial 120 轮。
- 每个 trial 严格包含 60 次“旧→新”和 60 次“新→旧”,再按固定 seed 洗牌,避免顺序偏差。
- 每个实现、每个场景共 360 个样本;短场景使用 batching。
- 使用
Bun.nanoseconds();报告聚合 median 和 p95。
- 每轮都对新旧返回值执行 JSON 严格等价检查;另覆盖 duplicate、unmatched、数组内容、错误与 malformed block。
结果
单位:毫秒/次。
| 会话规模 |
旧 median |
新 median |
median 加速 |
旧 p95 |
新 p95 |
p95 加速 |
| 1k messages / 1 artifact |
0.02630 |
0.02901 |
0.91× |
0.04004 |
0.04104 |
0.98× |
| 1k / 5 |
0.05384 |
0.03196 |
1.68× |
0.06358 |
0.04481 |
1.42× |
| 1k / 10 |
0.08886 |
0.03570 |
2.49× |
0.09094 |
0.03780 |
2.41× |
| 1k / 25 |
0.20054 |
0.05370 |
3.73× |
0.20179 |
0.05491 |
3.68× |
| 2k / 200 |
2.70905 |
0.28186 |
9.61× |
2.71983 |
0.29307 |
9.28× |
| 10k / 500 |
31.96035 |
0.91182 |
35.05× |
32.04902 |
0.95202 |
33.66× |
三个大场景的逐 trial median 加速也保持稳定:
- 1k / 25:3.742×、3.723×、3.741×;
- 2k / 200:9.756×、9.523×、9.547×;
- 10k / 500:34.873×、34.992×、35.061×。
所有规模和边界 fixture 均 equality: true。
边界说明
单 artifact 场景增加约 0.0027 ms(2.7 μs)中位耗时;p95 差约 1.0 μs。候选实现已延迟到第 2 个 artifact 才分配索引,绝对回退很小,但不应宣称“所有场景都加速”。从 5 个 artifact 开始 median 与 p95 均有收益,长会话收益明显。
建议优化
- 第 1 个 artifact 沿用直接查找,避免普通场景无条件分配 Map。
- 从第 2 个 artifact 开始只构建一次 first-result-wins 索引。
- 保持
findToolResult() 对重复 ID 取首个结果的语义。
- 增加多 artifact、duplicate ID 和 result-before-use 回归测试;计时 benchmark 不放进 CI。
查重
已检索开放/关闭 issue 和全部 PR,关键词包括 artifacts performance、artifact scanner、findToolResult、quadratic transcript。命中的 #1278 是 artifacts 功能引入 PR,不包含本优化,未发现同因问题。
问题概述
src/commands/artifacts/scanner.ts每发现一个 artifacttool_use,都会调用findToolResult(messages, toolUseId)从会话开头重新扫描全部消息。若会话有N条消息和A个 artifact,复杂度为O(A × N);artifact 数量随会话增长时会退化为O(N²)。这会直接影响长会话打开
/artifacts列表的响应时间。环境
3bb6b5746238c418138eb96d57765d79012edd961.3.13Linux 5.15.0-186-generic x86_64对比方案
候选实现保留首个 artifact 的直接查找路径;检测到第 2 个 artifact 后,仅一次遍历用户消息,为
tool_result建立 first-result-wins 的Map,后续按tool_use_id做O(1)查找。结果顺序、重复 ID、result 先于 use、数组 content、error 和 unmatched 行为均保持不变。基准方法
Bun.nanoseconds();报告聚合 median 和 p95。结果
单位:毫秒/次。
三个大场景的逐 trial median 加速也保持稳定:
所有规模和边界 fixture 均
equality: true。边界说明
单 artifact 场景增加约 0.0027 ms(2.7 μs)中位耗时;p95 差约 1.0 μs。候选实现已延迟到第 2 个 artifact 才分配索引,绝对回退很小,但不应宣称“所有场景都加速”。从 5 个 artifact 开始 median 与 p95 均有收益,长会话收益明显。
建议优化
findToolResult()对重复 ID 取首个结果的语义。查重
已检索开放/关闭 issue 和全部 PR,关键词包括
artifacts performance、artifact scanner、findToolResult、quadratic transcript。命中的 #1278 是 artifacts 功能引入 PR,不包含本优化,未发现同因问题。