Skip to content

Optimize VCS diff loading to be up to 98% faster#2586

Open
justsomelegs wants to merge 21 commits intopingdotgg:mainfrom
justsomelegs:t3code/9f93372b
Open

Optimize VCS diff loading to be up to 98% faster#2586
justsomelegs wants to merge 21 commits intopingdotgg:mainfrom
justsomelegs:t3code/9f93372b

Conversation

@justsomelegs
Copy link
Copy Markdown
Contributor

@justsomelegs justsomelegs commented May 8, 2026

What Changed

  • Moved checkpoint filesystem operations behind a generic VCS checkpoint capability instead of scripting Git directly in CheckpointStore.
  • Reworked VcsProcess.run and processRunner onto a shared capturedProcess primitive for one-shot collected process execution.
  • Optimized checkpoint diff generation by:
    • removing redundant checkpoint preflight checks on the diff path
    • resolving the VCS driver once per checkpoint operation
    • using explicit commit peeling (^{commit}) for checkpoint diff refs
  • Added a narrower full-thread diff lookup path and supporting tests.

Why

Opening diffs and switching turns was spending too much time in process execution overhead and checkpoint diff orchestration.

This branch improves that by:

  • reducing per-command process overhead in the hot path
  • moving checkpoint behavior behind the VCS abstraction instead of hand-assembling Git commands in the store
  • reducing Git revision-resolution cost for checkpoint refs in repos with large checkpoint ref namespaces

Benchmark Summary

Synthetic workload used for all numbers below:

  • 24 changed files
  • 690,422 patch bytes
  • 26,137 patch lines

Benchmarks were run sequentially to avoid contention between benchmark loops.

Mean Latency

Metric upstream/main Current branch
checkpointStore.diffCheckpoints 1179.81ms 72.84ms
checkpointDiffQuery.getTurnDiff 1649.32ms 52.05ms
parseTurnDiffFilesFromUnifiedDiff 12.42ms 11.97ms

Tail Latency (p99)

Metric upstream/main Current branch
checkpointStore.diffCheckpoints 2262.90ms 355.04ms
checkpointDiffQuery.getTurnDiff 2937.21ms 191.04ms
parseTurnDiffFilesFromUnifiedDiff 16.43ms 19.63ms

Key Measurements

Compared directly with upstream/main:

  • checkpointStore.diffCheckpoints: 1179.81ms -> 72.84ms mean (16.20x faster, 93.8% lower)
  • checkpointDiffQuery.getTurnDiff: 1649.32ms -> 52.05ms mean (31.69x faster, 96.8% lower)
  • checkpointStore.diffCheckpoints: 2262.90ms -> 355.04ms p99
  • checkpointDiffQuery.getTurnDiff: 2937.21ms -> 191.04ms p99

Before

before.vcs.optimisation.mp4

AFTER

vsc.after.optimisations.mp4

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • I included a video for animation/interaction changes

Note

Optimize VCS diff loading by delegating checkpoint operations to the Git driver

  • Moves all checkpoint logic (capture, restore, diff, delete, existence checks) from CheckpointStore into a new checkpoints API on GitVcsDriver, eliminating redundant git subprocess calls and ref-existence preflights before diffing.
  • Rewrites processRunner.ts with an Effect-based API using a ChildProcessSpawner service, typed errors (ProcessSpawnError, ProcessTimeoutError, ProcessOutputLimitError), structured ProcessRunInput/ProcessRunOutput, and outputMode: 'truncate' support instead of rejecting on limit.
  • CheckpointDiffQuery.getFullThreadDiff now uses a dedicated ProjectionSnapshotQuery.getFullThreadDiffContext to look up the canonical turn-0 checkpoint ref directly, skipping per-ref existence checks.
  • Renames truncateOutputAtMaxBytes to appendTruncationMarker across VcsProcess, GitVcsDriverCore, and all call sites to clarify the option's role.
  • Risk: runProcess API is now Effect-based and requires a ChildProcessSpawner service; all callers (terminal manager, repository identity resolver, environment label, source control discovery) have been updated but the signature change is breaking for any external consumers.

Macroscope summarized 01be4db.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 8, 2026

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 637efaa2-9c9b-42f1-92f4-9350c63c1d81

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:XXL 1,000+ changed lines (additions + deletions). labels May 8, 2026
@macroscopeapp
Copy link
Copy Markdown
Contributor

macroscopeapp Bot commented May 8, 2026

Approvability

Verdict: Needs human review

This PR restructures core VCS and checkpoint infrastructure, moving checkpoint operations into the Git driver and converting process spawning to Effect-native patterns. The architectural scope and changes to critical diff/checkpoint paths warrant human review despite being framed as a performance optimization.

You can customize Macroscope's approvability policy. Learn more.

Comment thread apps/server/src/capturedProcess.ts Outdated
Comment thread apps/server/src/stream/collectUint8StreamText.ts Outdated
Comment thread apps/server/src/processRunner.ts Outdated
Comment thread apps/server/src/vcs/GitVcsDriver.ts
Comment on lines +149 to +152
const getFullThreadDiff: CheckpointDiffQueryShape["getFullThreadDiff"] = (
input: OrchestrationGetFullThreadDiffInput,
) =>
Effect.gen(function* () {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Effect.fn

* Read only the narrow context needed to compute a full-thread diff from
* checkpoint 0 to a specific turn count.
*/
readonly getFullThreadDiffContext?: (
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

why optional?

}
const resolveRepositoryIdentityCacheKey = Effect.fn("resolveRepositoryIdentityCacheKey")(function* (
cwd: string,
runManagedProcess: ManagedProcessRunner,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

nit: DI the ChildProcessSpawner (Effect.provideService) and runProcess like normal

Comment on lines +36 to +44
function joinPath(...parts: ReadonlyArray<string>): string {
return parts
.map((part, index) => {
if (index === 0) return part.replace(/[\\/]+$/g, "");
return part.replace(/^[\\/]+|[\\/]+$/g, "");
})
.filter((part) => part.length > 0)
.join("/");
}
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

what happened to path.join. ?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@effect/vitest

truncatedMarker: input.appendTruncationMarker ? OUTPUT_TRUNCATED_MARKER : "",
timeoutBehavior: "error",
}).pipe(
Effect.mapError((cause) => {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

effect pattern i sometimes use is adding static methods like

class VcsProcessSpawnError extends ... {
  static fromProcessSpawnError = () => ...
}

sometimes ends up with cleaner business logic. Ref: https://github.com/pingdotgg/t3code/blob/main/packages/effect-acp/src/errors.ts#L50

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@effect/vitest and provide a test implemntation of the ChildProcessSpawner instead of writing scripts to FS?

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

Labels

size:XXL 1,000+ changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants