Skip to content

perf(tui): bound repeated-id transcript result lookup - #327

Open
liwen-aaa wants to merge 1 commit into
openpi-dev:mainfrom
liwen-aaa:perf/issue-185-viewport-window
Open

perf(tui): bound repeated-id transcript result lookup#327
liwen-aaa wants to merge 1 commit into
openpi-dev:mainfrom
liwen-aaa:perf/issue-185-viewport-window

Conversation

@liwen-aaa

@liwen-aaa liwen-aaa commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Problem

Refs #185. When several tool calls reuse one ID, findResult() linearly scans
the 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 the findResult() scan
    with an upper-bound binary search (14 additions, 6 deletions).
  • tests/extensions/shared/agent-transcript-pairing.test.ts: seven regressions
    covering 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 integration
is introduced by this PR. Rendering and cache contracts stay on the main-branch
implementation. The optional revision/generation inconsistency reported against
old head 9691b00 is 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).
  • Pairing and related transcript/page/adapter suites: 51/51 passed, including
    all seven new pairing tests.
  • The new index-read assertion fails against clean main: the 40-result fixture
    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 bash
    renderer assertion (undefined versus self), and git-info process exit-code
    handling (-1 versus 7). The renderer assertion also fails in a detached
    clean-main worktree. The process test passed in the isolated baseline run;
    its full-suite failure is reported rather than claimed resolved.
  • The runner exits on those Node failures, so the serial background-terminal
    phase was not reached. Vitest was run separately using the runner's
    *.spec.ts selection: 9 files, 130/130 passed.

Deterministic measurements with the same benchmark on main and this change:

512-item shape Longest per-ID index Main index reads PR index reads
Sequential distinct IDs 1 256 512
Separated 64-way distinct IDs 1 256 512
Repeated shared ID 256 32896 2306

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

  • User-visible: pairing semantics remain unchanged; repeated-ID lookup work is bounded.
  • Model-visible context/tools: none.
  • Runtime/lifecycle: none; no new cache invalidation contract.
  • Persisted config/data: none.
  • Compatibility/risk: singleton indices incur one extra array read. Tests cover
    strict ordering and pending/error behavior; the existing renderer stays intact.

@tt-a1i tt-a1i left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

我建议当前版本先不要合并。实现和测试本身很认真,性能数字也可复现;阻塞点不是正确性,而是当前收益不足以支撑新增的缓存架构。

当前证据:

  • 在 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 问题,是窗口缓存成立后必须处理的新失效场景;旧的全量渲染路径没有这一类缓存一致性风险。

建议缩小范围:

  1. 保留 findResult() 的二分查找及相应回归测试;这是小而明确的改进。
  2. 保留 benchmark 作为后续证据工具。
  3. 完整 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。

@liwen-aaa

Copy link
Copy Markdown
Contributor Author

感谢评审,三条意见全部接受。收缩已完成。过程中的测量改变了我对 #185 配对这一半问题的理解,其中一部分与我原先的 PR 描述矛盾,一并说明。

当前范围

  M  extensions/shared/agent-transcript.ts                       (+20 −6,仅 findResult)
  A  tests/extensions/shared/agent-transcript-pairing.test.ts    (7 个配对回归测试)
  A  benchmarks/child-transcript-pairing.ts                       (证据工具)

已完全移除: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 是我引入窗口缓存后才产生
、且只存在于该缓存内部的失效场景 —— 正是您第 4 点所指。把它们说成对现状的改进,夸大了本 PR 的价值。

我也验证了自己新增的 cwd/expanded 缓存键是否在修复既有问题:不是。在干净的 ba550bc 上,expanded 切换(含/不含 native renderer)和 cwd 变化下,warm 与 cold 渲染结果一致,无陈旧行
。因此不需要单独提 issue。

关于「保留二分查找」

同意保留,但依据与我原先给出的不同 —— 因为测量结果与我的预期相反。

在实际的 per-id 索引长度下,二分查找的数组读取次数多于线性扫描:

┌──────────────────────┬──────────────────┬────────────┬────────────┐
│ shape │ 最长 per-id 索引 │ 线性 reads │ 二分 reads │
├──────────────────────┼──────────────────┼────────────┼────────────┤
│ sequential 512 │ 1 │ 256 │ 512 │
├──────────────────────┼──────────────────┼────────────┼────────────┤
│ separated 64-way 512 │ 1 │ 256 │ 512 │
├──────────────────────┼──────────────────┼────────────┼────────────┤
│ shared-id 512 │ 256 │ 32896 │ 2306 │
└──────────────────────┴──────────────────┴────────────┴────────────┘

#185 点名的 64-way 并行分离形态不是退化情形:并行调用各自持有独立 id,per-id 索引长度为 1,线性与二分均为 O(1)。只有 id 被复用时索引才会变长。

那么 id 会复用吗?扫描本机 170 个 Pi session transcript,按线性化路径统计(会话是 parentId 树,按文件统计会混淆兄弟分支):

  files with branch points : 169
  linearized paths checked : 394
  results per tool id      : 15280 个 id,索引长度全部为 1
  max repeats in one message: 1

零复用。compaction 记录(全库 2 条)存储 summary 与 firstKeptEntryId,是截断而非消息重放,不会重新引入 id。

但构造上可达。直接驱动 workflowTranscriptDocument:

  legacy, no ids, 3 same-name pairs     longestPerId=1
  legacy, orphan results only           longestPerId=1
  provider REPEATS one call id          longestPerId=3
  mixed ids and missing ids, same name  longestPerId=2
  retry reusing one id 40 times         longestPerId=40

合成路径(workflow-tool-${index})按下标唯一,安全。第 4 行是不需要 provider 出错的情形:当 legacy Workflow 历史中部分条目携带 call id、同名的其他条目没有时,fallback 配对的
pending?.shift() 会将两者混合并产生重复 id。

也就是说,call id 唯一性是一项由 provider 保证、而 OpenPI 从不校验的不变量 —— 此处没有任何类型、断言或测试约束它。这才是二分查找的真实依据:它移除了对未受守卫的外部行为的隐式依
赖,代价是索引长度为 1 时多一次数组读取(512 items 下 renderMs 4.90 vs 4.81,噪声量级)。

我此前用「慢一倍」描述 256 vs 512,是用比例掩盖了可忽略的绝对差值,表述不够诚实。

调用点注释已改写为可被数据检验的版本:说明唯一性来源、实测语料结论、可达的重复路径、以及代价。新增测试构造长度 40 的 per-id 索引,先断言 fixture 确实建出该长度(避免测试空转),
再验证每个调用配对到自己的结果。

按要求推迟的部分

viewport/revision 缓存已移出本 PR。若将来重开,需要真实 AgentSessionPage 端到端 profile 证明确实占用帧预算,或 transcript 上限显著提高;并且按您的建议,先评估「稳定 document 的
整段正文缓存 + 动态 live tail」这一更小机制。

供将来参考的测量:512 项上限下 warm repaint 0.082 ms → 0.002 ms,而 cold open 约 16 ms 且不被窗口化方案改善。这与您「当前收益不足以支撑新增失效契约」的判断一致。

也感谢您在 9691b00 上的独立验证,尤其是 1875 组新旧 render 输出比对 —— 比我本地能做的更充分,因为完整套件在我的 Windows 机器上跑不完。

@tt-a1i tt-a1i left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

@liwen-aaa
liwen-aaa force-pushed the perf/issue-185-viewport-window branch from 9691b00 to 22a7fdd Compare September 10, 2026 01:04
@liwen-aaa liwen-aaa changed the title perf(tui): render child transcript by viewport window perf(tui): bound repeated-id transcript result lookup Sep 10, 2026
@liwen-aaa
liwen-aaa force-pushed the perf/issue-185-viewport-window branch from 22a7fdd to 62de68b Compare September 10, 2026 01:06
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.

2 participants