Skip to content

perf(windows): reduce startup command discovery and Git probe overhead - #6124

Open
simon-curtis wants to merge 4 commits into
pingdotgg:mainfrom
simon-curtis:perf/windows-startup
Open

perf(windows): reduce startup command discovery and Git probe overhead#6124
simon-curtis wants to merge 4 commits into
pingdotgg:mainfrom
simon-curtis:perf/windows-startup

Conversation

@simon-curtis

@simon-curtis simon-curtis commented Aug 11, 2026

Copy link
Copy Markdown

Windows startup spends seconds searching long PATH/PATHEXT lists and cleaning up already-exited Git probes. This PR reduces both costs, with behavior changes confined to Windows.

  • Command discovery: reuse directory listings across an editor-discovery pass and use indexed filename matching for spawn resolution. Skip missing PATH entries; retain direct probes for directories that cannot be listed. PATH order, case-insensitive matching, and executable-file validation are preserved.
  • Repository discovery: skip missing workspaces and disable post-exit cleanup for git rev-parse --show-toplevel and git remote -v. These commands do not leave child processes behind. A small Effect patch supports the Windows-only override; cancellation, timeout, and default process cleanup remain intact.

Compared with nightly v0.0.39-nightly.20260905.1286:

Median measurement Nightly This branch
Launch to backend ready 8.87 s 6.39 s
Launch to first sidebar snapshot 18.20 s 8.40 s
Editor discovery 2.28 s 62 ms

Both versions were built from source and used identical database snapshots, with three interleaved measured launches after a warm-up each. The 54% reduction measures time to the first sidebar snapshot with warm caches. The branch includes newer upstream commits, so this compares releases rather than isolating the patch. Individual runs and benchmark details.

Validation: 80 focused tests passed, 13 skipped; targeted lint and server typecheck passed. Tests cover resolution fallback, cache lifetime, native process cleanup, and preservation of Linux/macOS behavior.

Model: GPT-6. Harness: Codex in T3 Code.

@coderabbitai

coderabbitai Bot commented Aug 11, 2026

Copy link
Copy Markdown

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 Plus

Run ID: 4eaab204-5559-42cc-a1b9-f24199c759a8

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

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

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Aug 11, 2026
Comment thread apps/desktop/src/shell/DesktopShellEnvironment.ts Outdated
@@ -177,17 +177,20 @@ export const ClaudeDriver: ProviderDriver<ClaudeSettings, ClaudeDriverEnv> = {

const snapshotSettings = makeProviderSnapshotSettingsSource(effectiveConfig, serverSettings);
const snapshot = yield* makeManagedServerProvider<ProviderSnapshotSettings<ClaudeSettings>>({
maintenanceCapabilities,
maintenanceCapabilities: maintenanceCapabilities.get,

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.

🟠 High Drivers/ClaudeDriver.ts:180

maintenanceCapabilities.get() returns the npm updater immediately after ClaudeDriver.create(), even when claude on PATH actually resolves to a native or Homebrew install. Before the deferred maintenanceCapabilities.refresh completes, ProviderRegistry.getProviderMaintenanceCapabilitiesForInstance can therefore return the wrong update action, so an update requested during startup runs npm instead of claude update/Homebrew. makeProviderMaintenanceCapabilitiesSource initializes its current value via resolver.resolve(options) before command-path/realpath discovery, and that synchronous resolve falls back to the npm updater for a bare claude command. Consider initializing current with a non-actionable value (or gating maintenance access) until the deferred resolution completes.

🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/server/src/provider/Drivers/ClaudeDriver.ts around line 180:

`maintenanceCapabilities.get()` returns the npm updater immediately after `ClaudeDriver.create()`, even when `claude` on PATH actually resolves to a native or Homebrew install. Before the deferred `maintenanceCapabilities.refresh` completes, `ProviderRegistry.getProviderMaintenanceCapabilitiesForInstance` can therefore return the wrong update action, so an update requested during startup runs `npm` instead of `claude update`/Homebrew. `makeProviderMaintenanceCapabilitiesSource` initializes its `current` value via `resolver.resolve(options)` before command-path/realpath discovery, and that synchronous resolve falls back to the npm updater for a bare `claude` command. Consider initializing `current` with a non-actionable value (or gating maintenance access) until the deferred resolution completes.

Comment thread scripts/build-desktop-artifact.ts
Comment thread apps/desktop/src/shell/DesktopShellEnvironment.ts Outdated
Comment thread packages/shared/src/shell.ts Outdated
@simon-curtis simon-curtis changed the title perf(windows): reduce startup work and clarify long phases perf(windows): reduce startup work and clarify installer phases Aug 11, 2026
Comment thread apps/server/src/provider/providerMaintenance.ts Outdated
@macroscopeapp

macroscopeapp Bot commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This PR changes Windows command discovery and subprocess cleanup in shared production infrastructure, including a patched process spawner, so its runtime blast radius is broader than a small performance tweak. It also adds a file-level static-analysis suppression in a new test file, while an unresolved High finding describes a startup-time maintenance-action risk.

Not approved because:

  • 1 blocking correctness issue found at or above your repo's Minimum Blocking Severity

Adjust the Minimum Blocking Severity for this repo — including turning it Off — in Settings. You can add or adjust custom eligibility rules. Learn more.

@cursor cursor 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.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit fef06d741f8c710f0957139af036297f3f3aad90. Configure here.

Comment thread apps/server/src/provider/providerMaintenance.ts Outdated
@simon-curtis
simon-curtis marked this pull request as draft August 13, 2026 11:14

@CDVolvik CDVolvik 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.

Read the Windows shell half against today's main. CONFLICTING.

Desktop: drops the -NoProfile PATH probe entirely and keeps only the profile probe, merging process PATH + profile PATH + knownWindowsCliDirs. That is the ~2s startup win (each PowerShell spawn was ~2s). It also deletes the no-profile source #6356 is trying to make read Machine+User, so a CLI installed after launch still will not show up until the next process start unless the profile sees it.

Shared: directory listing + case-insensitive name map instead of probing every PATHEXT candidate, with a fallback when readDirectory fails (ACL / unreadable share). That is the right Windows lookup. Returning [command] when the input already has a PATHEXT suffix is also right — the old code generated three casings of the same extension.

Do not land this and #6356/#4896/#6301 independently; they all rewrite installWindowsEnvironment.

@simon-curtis simon-curtis changed the title perf(windows): reduce startup work and clarify installer phases perf(windows): speed up shell command discovery Aug 17, 2026
@simon-curtis
simon-curtis force-pushed the perf/windows-startup branch 2 times, most recently from 324294b to 96a86d6 Compare August 17, 2026 16:42
@simon-curtis simon-curtis changed the title perf(windows): speed up shell command discovery perf(windows): reduce first-start editor discovery time Aug 17, 2026
@simon-curtis

Copy link
Copy Markdown
Author

Scope update: I have reframed this PR around reducing first-start/editor-discovery time on Windows.

After comparing the original branch with current main and the overlapping Windows environment work, the earlier ~2-second startup result was attributable to removing a PowerShell PATH probe. That change affects PATH refresh semantics and conflicts with the other installWindowsEnvironment work, so it no longer belongs in this PR. The installer, packaging, provider-lifecycle, desktop environment, and WSL changes have also been removed.

What remains is the independently useful shared lookup optimization: list each Windows PATH directory once, match PATHEXT candidates case-insensitively, preserve PATH order, and fall back to the existing direct probes when listing fails. I also restored resolveCommandCandidates exactly to main, so this PR no longer changes candidate casing behavior.

A targeted five-run benchmark on this machine's 71-entry PATH and 12 PATHEXT values measured provider discovery at 199 ms → 49 ms and first editor discovery at 1,964 ms → 425 ms. This is a resolver benchmark, not an end-to-end startup claim.

@github-actions github-actions Bot added size:S 10-29 changed lines (additions + deletions). and removed size:L 100-499 changed lines (additions + deletions). labels Aug 17, 2026
Comment thread packages/shared/src/shell.ts Outdated
@simon-curtis
simon-curtis marked this pull request as ready for review August 17, 2026 17:25
@simon-curtis
simon-curtis force-pushed the perf/windows-startup branch 7 times, most recently from 99f0376 to d5a0e7a Compare August 26, 2026 08:27
@simon-curtis
simon-curtis force-pushed the perf/windows-startup branch 2 times, most recently from cfb0d3e to 9ecfbc4 Compare September 1, 2026 08:32
Simon Curtis and others added 2 commits September 2, 2026 11:03
Co-authored-by: macroscopeapp[bot] <170038800+macroscopeapp[bot]@users.noreply.github.com>
@t3dotgg

t3dotgg commented Sep 4, 2026

Copy link
Copy Markdown
Member

Note

🤖 GPT-6 Astra (preview) responding on behalf of Theo

This note is part of an automated cleanup pass.

Preserving these details from items reviewed in the cleanup pass.

Carryover from #6221 at 59849f94e2: retain the shell.test.ts listing-failure cases. PermissionDenied, Busy, and Unknown must fall back to direct executable probes, while NotFound and BadResource can skip the directory. Keep mixed-case filenames and PATH order intact. The cross-command directory reuse may be useful if Windows measurements still show repeated listings, but the two PRs' benchmarks use different machines and cannot establish which is faster.

Carry over the slow-discovery evidence from #5050 at 61278bee47. On the reported Windows host with 46 PATH entries and 12 PATHEXT entries, getConfig timed out near 5,000 ms on every call. Concurrent discovery finished in 4,787 ms in that report. Its focused test interrupts one caller during discovery, then requires a later caller to obtain editors. Check cold discovery and caller interruption while retaining bounded expiry and current Linux/WSL file-manager checks. These are reported measurements and a test case to retain, not results rerun here.

Keep the trace evidence from #4778 at dc7f1727a6 in the Windows resolver review. Its author reported 28,577 shell.isExecutableFile spans from 22 command lookups in 13.7 seconds, plus trace files rotating at 10 MB about every 40 seconds. The distinct code change makes isExecutableFile untraced. Main still traces that helper, although its command cache and VCS limits are now bounded. Check first-scan and miss-heavy trace cost with this PR. Do not copy the older unbounded cache or treat the reported timings as rerun results.

@simon-curtis simon-curtis changed the title perf(windows): reduce first-start editor discovery time perf(windows): reduce startup command discovery and Git probe overhead Sep 5, 2026
@simon-curtis

Copy link
Copy Markdown
Author

Pushed 6754baee4 and resolved the merge against upstream main. The implementation is now limited to Windows command discovery and Git-probe startup costs; the experimental UI, settlement, and auto-pull changes were removed.

I compared production source builds against nightly v0.0.39-nightly.20260905.1286 (09aac715), shallow-cloned with --depth 1. Both used identical database snapshots, the same machine/runtime, and isolated state. After discarding one warm-up per build, the measured launches were interleaved:

Process launch to first sidebar snapshot Run 1 Run 2 Run 3 Median
Nightly 18.345 s 16.574 s 18.201 s 18.201 s
This branch 8.200 s 8.885 s 8.404 s 8.404 s

That is 9.80 seconds / 54% less time to the first sidebar snapshot in this comparison. Median backend readiness improved from 8.87 s to 6.39 s; editor discovery from 2.28 s to 62 ms. These timings overlap and should not be added together.

These are warm-cache source-build measurements, not cold boots or a measurement of fully interactive UI readiness. Since the branch includes newer upstream commits, the result compares this branch with that nightly release rather than isolating only this patch.

Validation: 80 tests passed, 13 skipped, targeted lint and server typecheck passed. Native tests cover completed probes, cancellation, timeout, and preservation of default cleanup; platform tests keep the override Windows-only.

Model: GPT-6. Harness: Codex in T3 Code.

@github-actions github-actions Bot added size:L 100-499 changed lines (additions + deletions). and removed size:S 10-29 changed lines (additions + deletions). labels Sep 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L 100-499 changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants