Skip to content

perf(worktrees): run three worktree deletes at once so a batch's third delete doesn't wait for a slot - #24293

Closed
brennanb2025 wants to merge 1 commit into
mainfrom
brennanb2025/worktree-delete-limit-3
Closed

brennanb2025 wants to merge 1 commit into
mainfrom
brennanb2025/worktree-delete-limit-3

Conversation

@brennanb2025

@brennanb2025 brennanb2025 commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

What this fixes

Follow-up to #23837 (merged). When you delete several large worktrees at once, the third one waits for a free delete slot before git even starts on it, so its card shows "Deleting…" for an extra 6–14 s while nothing happens to it.

Scope: local and WSL worktree deletes from the desktop app, paired desktops, web, mobile and the CLI, only when three or more are being deleted at the same time on one machine. Single deletes and SSH worktrees are unchanged.

Background: #23837 moved the checkout delete back into git's own process (git worktree remove) and limited how many of those git deletes run at once on a host to two (WORKTREE_DELETE_CONCURRENCY), on the assumption that two already saturate one disk. Measuring it showed that assumption was wrong.

ELI5

Orca lets only a fixed number of worktree deletes run at the same time. With the limit at two, deleting three worktrees made the third wait for one of the first two to finish before it could even start. Raising the limit to three lets all three start together; each takes a little longer because they share the disk, but the whole batch finishes about 4 seconds sooner and the third card no longer waits for a slot.

What Changed

  • WORKTREE_DELETE_CONCURRENCY goes from 2 to 3 (src/main/git/worktree-delete-limit.ts), with the comment updated to the measured reason. The cap stays: it still bounds disk contention and the number of git processes for larger batches, since these deletes don't count against the limit Orca puts on its other git commands.
  • The limit's test now checks queueing in terms of the limit itself (it passes at 2 and at 3), instead of hard-coding two.
  • One comment that said "two-at-a-time" now says "concurrent-delete limit".

For the user: deleting three large worktrees at once finishes about 4 s sooner, and the third card starts its delete about 3 s after you confirm instead of 9–17 s. (The remaining ~3 s is Orca stopping that worktree's open terminal before deleting, which happens with any limit.)

Why

Measured on the M4Air Mac with three local builds of #23837 that differed only in this limit (2, 3, 8): delete three worktrees of 139,000 files each while creating three new ones, three interleaved rounds, load average 4–23.

limit 2 limit 3 limit 8
everything done (median) 21.6 s 17.6 s 15.2 s
per-round change vs 2 — −3.4 / −4.0 / −3.7 s −2.4 / −6.4 / −2.4 s
third delete's git starts (median) 13.4 s 2.7 s 3.0 s
worst main-process file read ≤ 35 ms in every run ≤ 35 ms ≤ 35 ms
new worktree ready after its request 0.3–1.1 s in every run same same

With three deletes, limits 3 and 8 run the same path (all three at once), so the gap between them is noise. Running three at once makes each delete slower (disk contention), but the batch finishes sooner in every round and nothing else in the app slows down.

Differences from the common pattern

  • Intended: the common pattern runs one worktree cleanup per machine at a time. Orca allows three because Orca measured that three finish a batch sooner with no responsiveness cost on its own delete path (git processes on a local disk).

Known weaknesses

  • Measured with one worktree size only (about 139,000 files each, all three the same size). The gain scales with how long the first deletes take: small worktrees see almost no difference, and a small delete queued behind two large ones gains the most. With much larger trees or a slower disk, the extra contention of three at once could cancel the gain; that is not measured.
  • Not measured: more than three deletes at once, slow or spinning disks, Windows with antivirus scanning, WSL worktrees (they share this limit), and network filesystems. The cap of three limits the exposure.
  • Leftover-file cleanup after git (for example the folder links Git for Windows leaves behind) and the startup finish of an interrupted delete run inside Orca's own process, now up to three at once. That path was not measured; it is bounded by the same cap.

Linked Issue

No ticket. Found by measuring #23837 (deleting several worktrees while creating several).

Visual Proof

Delete concurrency limit 2 vs 3 vs 8, three interleaved rounds on the M4Air: limit 3 finishes everything 3.4–4.0 s sooner in every round (median 17.6 s vs 21.6 s); the third delete's git starts at 2.6–3.4 s instead of 9–17 s; worst main-process file read stays ≤35 ms in every variant

Testing

  • src/main/git/worktree-delete-limit.test.ts passes at limit 3 and at limit 2 (queueing order, slot hand-off, slot freed on failure).
  • src/main/runtime/orca-runtime.test.ts passes.
  • tsc for the node and web projects; oxlint, oxfmt and the changed-code quality gate.
  • Live measurement on the M4Air as above (local builds, never pushed).

Review

Reviewed by a separate agent: the code change is sound. Only git worktree remove, its leftover cleanup and the startup finish of interrupted deletes run under this limit; branch cleanup and archive hooks stay one at a time per repo. A live race of 25 rounds (three concurrent removes plus one concurrent create in one repo, Git 2.50) had no failures and left no stale entries. The test fails if the limit is ignored, off by one, or hands slots out in the wrong order.

Agent skill upstream boundary

  • Not applicable.

Notes

Security: none. Cross-platform: measured on macOS; WSL and Windows share the cap and are unmeasured. Remote SSH: not touched. Mobile: not touched. Backwards compatibility: no stored data or wire change. Performance: covered above.

Checklist

  • This PR is small and focused
  • I explained what changed and why (ELI5, the user-facing before/after, the mechanism, and why over the alternatives)
  • Before/after screenshots or videos attached for UI changes, or N/A with reason
  • Self-reviewed for correctness, security, and performance
  • Cross-platform, SSH/remote, and path/shortcut impact considered (or N/A)
  • pnpm lint, pnpm typecheck, pnpm test, and pnpm build pass (or CI will cover; local preferred)

@brennanb2025

Copy link
Copy Markdown
Contributor Author

Review status: ready for review (head 4f1f95f)

Problem: after #23837, Orca runs at most two git worktree remove at once per machine, so when you delete three large worktrees together the third one sits on "Deleting…" for an extra 6–14 s before git even starts on it.

User-facing change: deleting three large worktrees at once finishes about 4 s sooner (median 21.6 s → 17.6 s, faster in every measured round), and the third card's delete starts about 3 s after you confirm instead of 9–17 s. File reads and new-worktree creation stay as fast as before.

What was fixed during review: nothing in the code; the PR description now says WSL deletes share this limit (unmeasured), states the 6–14 s figure that the limit actually causes, and adds the missing template sections.

Verified: a separate review traced everything that runs under the limit (only the git delete, its leftover cleanup and the startup finish of interrupted deletes; branch cleanup and archive hooks stay one at a time per repo), ran a live race of 25 rounds with three concurrent removes plus a create in one repo (no failures), and confirmed the test fails if the limit is ignored, off by one, or out of order. Readiness checklist: no P0/P1. CI: 18 pass, 0 fail.

Not verified / deferred: more than three deletes at once, slow or spinning disks, Windows with antivirus, WSL, and network filesystems are unmeasured; the in-process leftover cleanup (now up to three at once) was not measured. The cap of three bounds all of these.

@brennanb2025
brennanb2025 marked this pull request as ready for review October 1, 2026 18:17
@greptile-apps

greptile-apps Bot commented Oct 1, 2026 •

Copy link
Copy Markdown

RetriggerConfidence Score: 5/5

[Medium risk] Increases concurrent worktree deletion from two to three.

The PR appears safe to merge; no actionable defect was established.

Summary

This PR raises the host-wide concurrent worktree-delete limit from two to three, adjusts the queueing test to derive its expectations from the limit, and updates a timeout comment. No actionable issue was established.

Reviews (1) · Last reviewed commit: "perf(worktrees): run three worktree dele..."

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

✅ No new issues found.

Reviewed changes

  • WORKTREE_DELETE_CONCURRENCY 2 → 3 — src/main/git/worktree-delete-limit.ts. The main-process semaphore now admits three concurrent git worktree remove children. The JSDoc records the measured reason (a three-worktree batch finished ~4 s sooner; the cap still bounds disk contention and child count for larger batches).
  • Queueing test made limit-agnostic — src/main/git/worktree-delete-limit.test.ts. The test derives limit and firstWave from the constant instead of hardcoding [0, 1] / running: 2. It still pins the real behavior: only limit operations start initially, the limit-th +1 starts only after a slot frees, arrival order is preserved, and the snapshot returns to zero.
  • Comment correction — src/shared/worktree/archive-hook-removal-gate.ts now says "concurrent-delete limit" instead of "two-at-a-time".

Why this is sound

  • The limit is deliberately admission-exempt (admissionExempt: true at src/main/git/worktree-removal.ts:77), so it does not draw from the general/network admission budget. MAX_GIT_CHILDREN = 10 counts admitted children only (src/main/git/command-runner/git-admission-state.ts:11-13), so raising this constant does not violate that bound — the existing comment already anticipated a delete limit that moves independently.
  • Only git worktree remove and the leftover-file cleanup run under it; branch cleanup and archive hooks remain serialized one-per-repo (worktree-removal.ts:121), so the packed-refs/fetch --prune races that motivated that serialization are untouched.
  • The client reply timeout (worktreeRemovalReplyTimeoutMs) is a flat budget independent of the limit, so more concurrency only shortens queue wait — it makes timeouts safer, not tighter.
  • No stale references to the old value remain anywhere in the repo (searched WORKTREE_DELETE_CONCURRENCY, "two-at-a-time", "delete slot", docs).

One thing to carry forward, not a blocker: the measurement is macOS-only, and the PR body already discloses Windows/WSL/spinning and network disks as unmeasured. The cap of three bounds the exposure, so approving.

Pullfrog  | View workflow run | Using deepseek-v4.1-flash (free via Pullfrog for OSS) | 𝕏

@coderabbitai

coderabbitai Bot commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Advanced

Run ID: 21db86e5-ecb2-4910-a0ad-8a568cb7d07d

📥 Commits

Reviewing files that changed from the base of the PR and between 3135fbb and 4f1f95f.

📒 Files selected for processing (3)
  • src/main/git/worktree-delete-limit.test.ts
  • src/main/git/worktree-delete-limit.ts
  • src/shared/worktree/archive-hook-removal-gate.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 6 remain after this review.


📝 Walkthrough

Walkthrough

The worktree delete concurrency limit increases from two to three. The concurrency test now uses the configured limit to size its gates and check queue progression. The timeout documentation refers to the host’s concurrent-delete limit.

Priority: ⬇️ Low

Merge Risk: ⚪ Minimal · up to 4f1f9

Three-worktree deletion batches can start the third delete sooner while remaining capped at three concurrent deletes. No concrete issue in the supplied review context blocks merging.

Security Architecture Review

Security architecture risk: 🔵 Low · up to 4f1f9

The change permits one additional simultaneous deletion on a machine while retaining existing safety checks and queue limits. No introduced security issue was identified, but interruption handling and caller authentication were not fully verified.

Retained concerns
No architecture-level concerns identified.

Security review details

Security Blast Radius

  • inferred — The incremental exposure is one additional simultaneous Git removal and associated filesystem cleanup within the existing local deletion scope, rather than a new deletion destination or authority boundary.

Trust Boundaries and Controls

  • observed — Inspected runtime callers join pending same-worktree removals. Local acceptance is serialized per repository and rechecks pending ownership after waiting, so an additional global slot does not itself create another accepted deletion of that worktree.
  • observed — Before local deletion is accepted, registration is refreshed, lock and cleanliness checks run, and a watcher-removal gate is acquired. A failed archive hook requires its explicit waiver rather than being implicitly waived by force.

Resilience and Maintainability Implications

  • observed — Interrupted-removal recovery checks registration and recorded checkout identity before forced completion, rejecting a replacement checkout at the same path. Normal completion releases the watcher gate in finally, and Git removal invalidates derived worktree state on exit.
  • observed — Queued limiter waiters have no explicit cancellation-removal mechanism. Git execution receives the checkout abort signal after admission; complete interruption and recovery behavior was not established by the inspected source and tests.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 1 functions across 3 files.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly and concisely describes the primary change: increasing worktree delete concurrency to three to prevent the third delete from waiting for a slot.
Description check ✅ Passed The description is detailed and covers the change, user impact, rationale, measurements, testing, limitations, compatibility considerations, visual proof, and checklist. It does not provide a linked i…
✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Autopilot is currently an internal CodeRabbit preview.


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.

@brennanb2025

Copy link
Copy Markdown
Contributor Author

Closing this: a size sweep showed that raising the limit to three doesn't make worktree deletes faster overall, so the limit stays at two.

What was measured: deleting three worktrees at once while creating three, at four sizes, limit 2 vs limit 3, three interleaved rounds each (24 runs, M4Air Mac, on top of main 0f91540).

Size Everything done, limit 2 → 3 Cards
Small (3 × ~2,000 files) 3.2 → 3.5 s no change; each delete takes under a second
Large (3 × ~139,000 files) 27.3 → 25.8 s, rounds disagree (−6.0 / +3.9 / +0.1 s) the third stops waiting, but the other two finish later (16.4 → 25.3 s)
Mixed (2 large + 1 small) 17.8 → 15.7 s the small one shows "Deleting…" for 3.3 s instead of 17.3 s
Extra-large (3 × ~417,000 files) 70.0 → 67.5 s the other two finish later (~43 → ~66 s)

Why it's closed: the disk does the same work either way, so the total barely moves; the earlier "about 4 s faster" result did not reproduce cleanly. The limit only changes which cards wait: three helps a small worktree deleted alongside large ones, but makes the more common equal-size batch show "Deleting…" longer on average. File reads and new-worktree creation stayed fast at every size in both arms.

Delete limit 2 vs 3 across worktree sizes, three interleaved rounds per limit: everything-done barely moves at any size (small 3.2 vs 3.5 s, large 27.3 vs 25.8 s, mixed 17.8 vs 15.7 s, extra-large 70.0 vs 67.5 s); the third card drops from 17.3 s to 3.3 s only when it is the small one; with equal sizes the other cards finish later (large 16.4 → 25.3 s, extra-large 42.9 → 66.4 s)

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.

1 participant