Repository navigation
perf: window drift no longer forces a full rebuild (#99) - #113
Merged
Carl723000 merged 1 commit intoSep 23, 2026
Merged
Conversation
On a long history the rolling window is always drifting past something: some file's oldest event has just left it, so the file arrives as a 'cutoff' rebuild, or its stored aggregate is rebased in place. The analysis fast path demanded "appends and nothing else", so either case rejected it and every refresh re-read the whole corpus. Measured on a 650-file, 1.4 GB history with several agents running: 136 of 140 refreshes re-read every body to serve one appended file — around 60 s of parse time per refresh, roughly once a minute, which is what pegged the extension host. Neither case invalidates the other files. A 'cutoff' rebuild is assigned only when the body on disk is unchanged, so the file owns exactly the UUIDs it owned before and cannot preempt a later owner; a rebase only narrows an aggregate that is already stored, and the UUIDs it drops are handed to the ownership pass, which re-plans precisely those files that could claim them. What does invalidate every stored contribution is a changed analysis context — no prior runtime, a different time zone, a different window length — and that still forces the rebuild, as do deletions, moves and a cutoff moving backward. The guards that matter keep their tests: a rebuilt earlier file preempting a later UUID owner, and an append that gives a zero-timestamp file its first timestamp, both still fall back to the full rebuild.
|
🤖 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. |
This was referenced Sep 23, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Follow-up to #109, #111 and #112, from the same profiling session: with those merged, the extension host was still pegged, and the incremental loader still re-read the whole corpus on almost every refresh.
What happens
On a long history the rolling window is always drifting past something. Some file's oldest event has just left it, so either the file arrives as a
'cutoff'rebuild, or its stored aggregate is rebased in place. The analysis fast path demanded "appends and nothing else", so either case rejected it and the refresh fell back to re-reading every body.Measured on a 650-file, 1.4 GB history with several agents appending concurrently — the extension's own diagnostics:
One file changed, 650 bodies read, ~50 s of parse time — repeated on every watch tick, about once a minute. 136 of 140 refreshes in one session took that path; the fast path was effectively unreachable on this machine.
Why this is safe
Neither case invalidates the other files:
'cutoff'rebuild is assigned only when the body on disk is unchanged (bodyUnchanged, where the reason is chosen) — the file is re-read solely to recompute its aggregate under the new cutoff. It therefore owns exactly the UUIDs it owned before and cannot preempt a later owner.What genuinely invalidates every stored contribution is a changed analysis context — no prior runtime, a different time zone, a different window length — and that still forces the rebuild, as do deletions, moves and a cutoff moving backward.
The guards that matter keep their tests, and I confirmed they still fail a broader version of this change: a rebuilt earlier file preempting a later content UUID owner, and an append that gives a zero-timestamp file its first timestamp (which reorders files, and with them ownership). Both still fall back to the full rebuild.
Test
the window drifting past an old event keeps the refresh incremental— one file's oldest event leaves the window while another session appends. It fails onmainwith "window drift re-read the whole corpus: 32 bodies" and passes here, and it assertscontentAnalysisequals what the full loader produces, so the faster path is checked for agreement, not just for speed.Effect in practice
Same machine and history, before and after, counted from the extension's log:
Full test run is unchanged against
mainon my machine: the same 8 pre-existing failures (Windows symlink and file-locking tests), plus the new test.There is a second, narrower cause of the remaining full rebuilds — a file that is appended to and has an event leave the window in the same refresh is planned as
rebuild:source, which still rejects the fast path. That one needs care around UUID ownership for the appended lines, so I left it out of this PR rather than widen the change.🤖 Generated with Claude Code