Skip to content

perf(git): batch context-store index writes on isomorphic-git 1.44.2 - #1423

Merged
TheGreatAxios merged 2 commits into
mainfrom
cl-10654-isomorphic-git-1442-batch-remove-hot-path-perf
Oct 15, 2026
Merged

TheGreatAxios merged 2 commits into
mainfrom
cl-10654-isomorphic-git-1442-batch-remove-hot-path-perf

Conversation

@TheGreatAxios

Copy link
Copy Markdown
Collaborator

Summary

  • Floats isomorphic-git to 1.44.2 via the existing ^1.27.2 catalog range (single lock resolution change; 1.42.7 index-write-once-per-walk and 1.43.3 packfile-checksum-once land on the context store's hot paths for free).
  • Batches the context store's per-file add/remove loop (src/session/optimized-context-store.ts:~1335) into array-form calls on 1.43.0+ — one GitIndexManager.acquire per call instead of one index write per path. On-error net state preserved: the same resetIndexPaths(dir, extraPaths) reset covers the add∪remove union, so a mid-batch failure still leaves nothing staged. Sole behavioral delta: multiple simultaneous add failures surface as MultipleGitError instead of the first error; the surrounding catch is type-agnostic.
  • The findRoot() conversion for project-key was evaluated and declined with evidence: the API is async-only while all four consumers (session/index.ts, crash/report.ts, permission/path-restriction.ts, config.ts) are synchronous by design, and findRoot ignores GIT_DIR/GIT_WORK_TREE/core.worktree semantics that rev-parse --show-toplevel honors — different semantics under worktrees and env-var overrides (probes showed matching behavior under plain worktrees/submodules; the env-var cases are the decliners).

Verification

  • bun run check exit 0: full one-process suite 8939 pass / 0 fail across 581 files.
  • Focused: bun test src/session/optimized-context-store.test.ts 58 pass / 0 fail; bun test src/session 563 pass / 0 fail across 41 files.
  • Lock diff is exactly one line (isomorphic-git 1.41.9 → 1.44.2); no pin change, so the known bun re-dedupe shake (tracked in CL-10681) does not apply.

Fixes CL-10654

The store's per-file add/remove loop forced one index write per path;
array-form add/remove stage everything inside one acquire and keep the
on-error net state (nothing staged) identical via the same reset path.
Multiple add failures now surface as MultipleGitError instead of the
first error; the surrounding catch is type-agnostic.
@linear-code

linear-code Bot commented Oct 14, 2026

Copy link
Copy Markdown

CL-10654

@corbits-triage

corbits-triage Bot commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

Superseded by the comment below.

@corbits-triage

corbits-triage Bot commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

Superseded by the comment below.

@corbits-triage

corbits-triage Bot commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

Triage: Unsure

A maintainer will review this pull request.

@TheGreatAxios
TheGreatAxios changed the base branch from cl-10658-pin-bump-bundle-types-bun-oxlintoxfmt-hono-drizzle-safe to main October 15, 2026 19:17
Array git.remove throws before the index write, so swallowing
that error committed every removed path still staged. Omit the
failing path and write the rest once. If nothing can be
unstaged, fail the commit instead.
@TheGreatAxios
TheGreatAxios merged commit 92b3dc4 into main Oct 15, 2026
13 checks passed
@TheGreatAxios

Copy link
Copy Markdown
Collaborator Author

Independent perf verification for this PR (measure-only lane, no source touched).

Method: benchmark pitting the exact pre-CL loop (git show 10042685: per-path git.remove) against the landed code (optimized-context-store.ts:1927-1949: batch + omit-one-out retry) on synthetic repos (fresh repo per run, 1 warmup + 7 reps at N=10/100, 5 reps at N=1000, 3 full runs), isomorphic-git 1.44.2.

  • fs proof: batch performs exactly 1 .git/index write; per-path performs exactly N. Every run, deterministic. (Lock writes 0 both sides — acquireLock is an in-process mutex.)
  • Wall medians: N=10 → ~6–9x (0.19–0.31 ms vs 1.61–1.79 ms); N=100 → ~75–135x (0.23–0.36 ms vs 16.9–49.2 ms); N=1000 → ~1125–1160x (0.53–0.54 ms vs 602–621 ms). Batch time is flat; per-path is linear. Perf claim CONFIRMED, effect scales with N.
  • On-error net-state equivalence CONFIRMED on all four fault tests: persistent path fault → byte-identical statusMatrix; transient EIO → identical state at write cost 13 (old) vs 3 (new); persistent EIO on batch → abort-before-write, index sha unchanged; cross-strategy restore via resetIndexPaths → identical snapshots.

No follow-up needed — recording the numbers here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant