perf(tui): bound repeated-id transcript result lookup - #327
Conversation
tt-a1i
left a comment
There was a problem hiding this comment.
我建议当前版本先不要合并。实现和测试本身很认真,性能数字也可复现;阻塞点不是正确性,而是当前收益不足以支撑新增的缓存架构。
当前证据:
- 在 512 项生产上限下,warm repaint 约从 0.082 ms 降到 0.002 ms;两者都远低于 16 ms 帧预算,PR 也明确说明目前没有可见卡顿。
- 更接近帧预算的 cold open 约 16.6 ms,而本方案不改善 cold open。
- 本次增加约 590 行生产逻辑,引入 items/pairing identity、行高和前缀和、theme generation、cwd、expanded、live tool、per-tool revision 和 ledger generation 等缓存失效契约。今后 transcript、compaction 或工具渲染发生变化时,这些都成为维护责任。
- PR 中修复的 same-length replacement 和 unrevisioned renderer row-total 问题,是窗口缓存成立后必须处理的新失效场景;旧的全量渲染路径没有这一类缓存一致性风险。
建议缩小范围:
- 保留 findResult() 的二分查找及相应回归测试;这是小而明确的改进。
- 保留 benchmark 作为后续证据工具。
- 完整 viewport/revision 缓存请在真实 AgentSessionPage 端到端 profile 证明当前实现明显占用帧预算,或 transcript 上限准备显著提高时再引入;届时也请先评估“稳定 document 的整段正文缓存 + 动态 live tail”这种更小机制。
我在 exact head 9691b00 上验证:bun run check 通过;专项测试 24/24;全量 1092 通过、1 项平台跳过;GitHub Node 22/24 和 Windows checks 全绿;另外对 1875 组 transcript 组合做了旧/新 render 输出比对,结果一致。没有发现模型上下文、消息、压缩或持久化状态影响。这里请求修改的是方案边界和投入产出比,不是声称存在未证实的运行时 bug。
|
感谢评审,三条意见全部接受。收缩已完成。过程中的测量改变了我对 #185 配对这一半问题的理解,其中一部分与我原先的 PR 描述矛盾,一并说明。 当前范围 已完全移除:beginFrame/窗口渲染、前缀和 layout 缓存、per-tool revision、cwd/expanded 入缓存键、AgentSessionPage 改动。 bun run check 通过;配对测试 7/7;相关套件 42/43(1 项为既有的 Windows 路径分隔符差异)。 更正原 PR 描述中的一处错误 我原先写本 PR "fixes two row-total bugs found while measuring",这个表述是错的,我撤回。 旧路径的 rowCount 取自已完成的全量渲染(agent-session-page.ts:243-249,this.rowCount = transcript.length),结构上不可能出现行总数与实际不符。那两个 bug 是我引入窗口缓存后才产生 我也验证了自己新增的 cwd/expanded 缓存键是否在修复既有问题:不是。在干净的 ba550bc 上,expanded 切换(含/不含 native renderer)和 cwd 变化下,warm 与 cold 渲染结果一致,无陈旧行 关于「保留二分查找」 同意保留,但依据与我原先给出的不同 —— 因为测量结果与我的预期相反。 在实际的 per-id 索引长度下,二分查找的数组读取次数多于线性扫描: ┌──────────────────────┬──────────────────┬────────────┬────────────┐ #185 点名的 64-way 并行分离形态不是退化情形:并行调用各自持有独立 id,per-id 索引长度为 1,线性与二分均为 O(1)。只有 id 被复用时索引才会变长。 那么 id 会复用吗?扫描本机 170 个 Pi session transcript,按线性化路径统计(会话是 parentId 树,按文件统计会混淆兄弟分支): 零复用。compaction 记录(全库 2 条)存储 summary 与 firstKeptEntryId,是截断而非消息重放,不会重新引入 id。 但构造上可达。直接驱动 workflowTranscriptDocument: 合成路径(workflow-tool-${index})按下标唯一,安全。第 4 行是不需要 provider 出错的情形:当 legacy Workflow 历史中部分条目携带 call id、同名的其他条目没有时,fallback 配对的 也就是说,call id 唯一性是一项由 provider 保证、而 OpenPI 从不校验的不变量 —— 此处没有任何类型、断言或测试约束它。这才是二分查找的真实依据:它移除了对未受守卫的外部行为的隐式依 我此前用「慢一倍」描述 256 vs 512,是用比例掩盖了可忽略的绝对差值,表述不够诚实。 调用点注释已改写为可被数据检验的版本:说明唯一性来源、实测语料结论、可达的重复路径、以及代价。新增测试构造长度 40 的 per-id 索引,先断言 fixture 确实建出该长度(避免测试空转), 按要求推迟的部分 viewport/revision 缓存已移出本 PR。若将来重开,需要真实 AgentSessionPage 端到端 profile 证明确实占用帧预算,或 transcript 上限显著提高;并且按您的建议,先评估「稳定 document 的 供将来参考的测量:512 项上限下 warm repaint 0.082 ms → 0.002 ms,而 cold open 约 16 ms 且不被窗口化方案改善。这与您「当前收益不足以支撑新增失效契约」的判断一致。 也感谢您在 9691b00 上的独立验证,尤其是 1875 组新旧 render 输出比对 —— 比我本地能做的更充分,因为完整套件在我的 Windows 机器上跑不完。 |
tt-a1i
left a comment
There was a problem hiding this comment.
Reviewed exact live head 9691b00.
The PR ref does not contain the narrowed implementation described in the author reply and revised #185 scope. The live diff is still six files and +1553/-54, including beginFrame, prefix-sum layout caches, per-tool revisions, viewport integration, and the large window suite. It also conflicts with current main in agent-session-page.ts and agent-transcript.ts.
- [P1] The review resolution and mergeable code disagree. The author said the viewport/cache architecture was removed and only the small findResult slice remained, but no such commit is on the PR. Merging would land the explicitly withdrawn design, not the agreed revision.
- [P2] revision() and generation() are independently optional, which can leave a permanently stale row total. An exact-head probe with revision but no generation produced warm rowCount 41 versus cold 50 after output growth.
- [P2] The admitted baseline benefit is about 0.08 ms at the existing 512-item ceiling, with no visible lag or cold-open improvement; that evidence does not justify the new cache/invalidation lifecycle.
Please push the promised reduced commit, or close/supersede this stale PR. Old exact-head CI cannot validate the unresolved current-main conflicts.
9691b00 to
22a7fdd
Compare
22a7fdd to
62de68b
Compare
Problem
Refs #185. When several tool calls reuse one ID,
findResult()linearly scansthe growing per-ID result index for each call. Repeated lookups can therefore
be quadratic in that index's length. Distinct IDs, including the 64-way
parallel-call shape, have constant-size indices and do not have this problem.
This replaces the withdrawn viewport/cache implementation following review.
The former row-total issues were introduced by that implementation; they are
not claimed as fixes to the existing full-render path.
Value
Bound repeated-ID pairing lookup without adding rendering caches or lifecycle
contracts. Preserve selection of the first result strictly after its call.
This is a small defensive improvement, not a claim of visible latency reduction
or faster cold opening at the current 512-item transcript limit.
Approach
The diff against current main contains exactly three files:
extensions/shared/agent-transcript.ts: only replace thefindResult()scanwith an upper-bound binary search (14 additions, 6 deletions).
tests/extensions/shared/agent-transcript-pairing.test.ts: seven regressionscovering ordering, duplicate IDs, parallel calls, errors, missing results,
and a deterministic bound on index reads for a long repeated-ID index.
benchmarks/child-transcript-pairing.ts: measure sequential, separated,and repeated-ID shapes using index reads and cold-render wall time.
No
beginFrame, prefix-sum layout, per-tool revisions, or viewport integrationis introduced by this PR. Rendering and cache contracts stay on the main-branch
implementation. The optional revision/generation inconsistency reported against
old head
9691b00is removed with the withdrawn implementation.Validation
Rebased on main
5bf2fe2. Windows, Node 24.16.0, Pi SDK/TUI 0.85.1.Dependencies installed with
bun install --frozen-lockfile.bun run check: passed (web build, format, lint, types and contract checks).all seven new pairing tests.
performs 820 reads, exceeding its logarithmic bound. It passes with this PR.
bun run test: Node phase completed in 83.3 seconds: 1435 tests, 1423 passed,2 failed, 10 skipped. Failures: the existing file-mutation-display
bashrenderer assertion (
undefinedversusself), and git-info process exit-codehandling (
-1versus7). The renderer assertion also fails in a detachedclean-main worktree. The process test passed in the isolated baseline run;
its full-suite failure is reported rather than claimed resolved.
phase was not reached. Vitest was run separately using the runner's
*.spec.tsselection: 9 files, 130/130 passed.Deterministic measurements with the same benchmark on main and this change:
The extra read for singleton indices is explicit; wall times are noisy and do
not establish an end-to-end UI speedup. No graphical smoke or model invocation
is claimed for this lookup-only change.
Impact
strict ordering and pending/error behavior; the existing renderer stays intact.