Skip to content

perf: an appended file leaving the window stays incremental (#99) - #114

Merged
Carl723000 merged 2 commits into
ClaudeCodeUsage:mainfrom
rsyuzyov:fix/window-rebase-append
Sep 23, 2026
Merged

Carl723000 merged 2 commits into
ClaudeCodeUsage:mainfrom
rsyuzyov:fix/window-rebase-append

Conversation

@rsyuzyov

Copy link
Copy Markdown
Contributor

Builds on #113 — its commit is the first of the two here, so please take #113 first and this will shrink to the second commit. Same profiling session as #109/#111/#112.

What is left after #113

#113 stopped the window's ordinary drift from forcing a full rebuild: full rebuilds went from 136 of 140 refreshes to 3 of 53. The ones that remained still cost 50-120 s each, and they had a single cause — the file that is appended to in the very refresh where one of its own events leaves the window.

Its stored aggregate still counts the expired event, so a tail read cannot serve it: the file genuinely has to be re-read in full. Until now that made it indistinguishable from a mid-file edit — it was planned as 'source', which rejects the fast path and re-reads every body. On a machine running several agents the pairing is routine, because sessions append constantly and on a long history the window is always drifting past something.

Worth noting how invisible this was from the source: such a file is classified in the needsAnalysisBody branch, which runs before the append/rebuild classification below it, and both produce a kind: 'rebuild' plan. Only a debug run made it visible that one plan was being turned into 683.

Why this is safe

Such a file only grew. It keeps every UUID it owned and can gain only new ones — the same shape as a plain append. So it is planned as 'window', allowed on the fast path, and put through the same ownership probe after parsing that a plain append gets: if one of its appended lines carries a UUID owned by a later file, the full rebuild still happens.

A genuine mid-file edit stays 'source': the append prefix and boundary checks are exactly what tell the two apart, and they are what grewOnly evaluates.

The same reason covers the other shape of the pairing, where the cheap rebase succeeds but changes the payload — that append was already being downgraded to a rebuild, and it is a window rebuild too, not a source edit.

Test

a file that is appended to while losing an event to the window stays incremental — it fails on the parent commit with "an appended file losing an event re-read the whole corpus: 8 bodies", and it asserts contentAnalysis equals what the full loader produces, so agreement is checked alongside the speed.

Measured

Same machine and history as #113, one hour of ordinary work with several agents appending:

full rebuilds ordinary tick
before both fixes 136 of 140 650 bodies, 50-98 s
after #113 3 of 53 (8 min) 1-9 bodies, 0.5-2 s
with this change 3 of 224 (1 hour) 1-12 bodies, 0.4-24 s

One of those three is the legitimate cold start, so the remaining full rebuilds went from roughly one every three minutes to one every half hour. I have not chased what causes the last two, and this change does not claim to.

Full test run matches main on my machine: the same 8 pre-existing failures (Windows symlink and file-locking tests), plus the new test.

🤖 Generated with Claude Code

@github-actions github-actions Bot added the fix Patch — bug fix label Sep 22, 2026
@github-actions

Copy link
Copy Markdown

🤖 Automated first-pass review

The configured analysis model did not return a usable analysis for this pull request. The item has still been received and remains available for maintainer review.

To help with review, please ensure the change summary, tests, and any user-facing documentation or localization updates are included.


🤖 Posted automatically by CCU Bot — not a maintainer decision.

…deUsage#99)

Follow-up to the previous window-drift fix, from the same measurement: full
rebuilds became rare but did not stop, and the remaining ones each cost 50-120 s
of parse time.

The remaining cause is the file that is appended to in the very refresh where
one of its own events leaves the window. Its stored aggregate still counts the
expired event, so a tail read cannot serve it and the file has to be re-read in
full. Until now that made it indistinguishable from a mid-file edit — it was
planned as 'source', which rejects the analysis fast path and re-reads every
body. On a machine with several agents the pairing is routine: sessions append
constantly, and on a long history the window is always drifting past something.

Such a file only grew. It keeps every UUID it owned and can gain only new ones,
which is exactly the shape of a plain append, so it is planned as 'window' and
allowed on the fast path — and, like an append, it is put through the ownership
probe after parsing: if one of its lines carries a UUID owned by a later file,
the full rebuild still happens. A genuine mid-file edit remains 'source', since
the append prefix and boundary checks are what tell the two apart.

The same reason covers the second shape of the pairing, where the cheap rebase
succeeds but changes the payload: that append was already being downgraded to a
rebuild, and it is a window rebuild too, not a source edit.

Test: `a file that is appended to while losing an event to the window stays
incremental` — it fails on the parent commit with "re-read the whole corpus:
8 bodies" and asserts the result equals what the full loader produces.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@Carl723000
Carl723000 force-pushed the fix/window-rebase-append branch from 841d542 to 79d9993 Compare September 23, 2026 09:44
Parse changed Claude files in canonical order when an append and a window rebuild happen together. The new regression fails before this fix and matches the full loader afterward.

Co-authored-by: OpenAI Codex <215057067+openai-codex[bot]@users.noreply.github.com>
@Carl723000
Carl723000 merged commit 7df7a35 into ClaudeCodeUsage:main Sep 23, 2026
4 checks passed
@Carl723000

Copy link
Copy Markdown
Collaborator

Thanks @rsyuzyov for the careful profiling and the follow-up to #113. The append-plus-expiry case is a meaningful improvement for long Claude histories. During review I added a mixed-file UUID ownership regression and a small ordering correction in this same PR, so the incremental result still matches the full loader. I appreciate the measured results and the clear explanation. Merged after the Node, UI, and package checks passed.


🤖 Generated with OpenAI Codex

@Carl723000 Carl723000 mentioned this pull request Sep 23, 2026
7 of 11 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

fix Patch — bug fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants