Throttle initial Git repository.status() across repositories#318862
Merged
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
Throttles the initial fire-and-forget repository.status() calls in the git extension's Model.openRepository() through a model-level Limiter<void>(5), preventing the extension host from being killed when opening large multi-root workspaces (~50+ git repos) where each status fans out ~8 git subprocesses simultaneously.
Changes:
- Import
Limiterfrom./util. - Add a private
_initialStatusLimiter = new Limiter<void>(5)field onModel. - Route the initial
repository.status()call through the limiter inopenRepository.
Show a summary per file
| File | Description |
|---|---|
| extensions/git/src/model.ts | Adds a 5-way concurrency limiter around initial repository.status() calls so SCM registration still happens immediately, but the per-repo subprocess/parse burst is bounded. |
Copilot's findings
- Files reviewed: 1/1 changed files
- Comments generated: 0
Contributor
Author
|
Exploration build pipeline: https://dev.azure.com/monacotools/Monaco/_build/results?buildId=443081&view=results |
lszomoru
approved these changes
May 29, 2026
dmitrivMS
marked this pull request as ready for review
May 29, 2026 22:10
Contributor
Author
|
Tested with 30 repos and on Windows, it looks ok, but also asked customer to confirm if the crash is gone in their scenario. |
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 subscribe to this conversation on GitHub.
Already have an account?
Sign in.
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.
Fixes #318279
Fixes #318764
Problem
In workspaces with many git repositories (~50+ folders in a multi-root
.code-workspace), the extension host gets killed ~25–30s after startup, auto-restarts, and crashes in a loop. The reporter'sexthost.logshows thousands of[Decorations] CAPPING events from decorations provider vscode.gitwarnings just before each kill, and the cadence matches the IPC unresponsive watcher firing after missed pings.git.enabled: falseis a known workaround.Root cause
Model.openRepository()ends with a fire-and-forgetrepository.status()for every repo discovered during the initial scan. Each_updateModelState()fans out ~8 git subprocesses (HEAD,remotes,submodules,worktrees,getStatus,getRefs, ...) and then parses the output on the ext-host's single thread. With N repos opening throughPromise.all(... openRepository ...)indoInitialScan, we get ~N×8 in-flight git subprocesses and a large blocking parse burst. For N≈50 that's enough to starve IPC pings and trip the unresponsive-host kill.The decoration
CAPPINGwarnings are a symptom of the same overload (each completed status fires a large decoration delta), not the cause.Fix
Throttle the initial fire-and-forget
repository.status()calls across repositories via a model-levelLimiter<void>(5). The repo is still registered with SCM immediately (this.open(repository)runs unchanged); only the resource/decoration population is throttled, which was already async.Concurrency 5 matches existing uses in extensions/git/src/repository.ts and extensions/git/src/git.ts — enough parallelism to keep cores busy without saturating the host.
Applies to runtime opens too (workspace-folder additions,
eventuallyScanPossibleGitRepositories), so the same crash can't be reproduced by adding folders incrementally.Verification
tsc -p extensions/git --noEmit).Not in scope
git rev-parse --show-toplevelcalls for subfolders of already-opened repos (previously explored in Avoid unncessary git rev parse calls #313856) would further cut process count but don't change the crash dynamics; better as a follow-up so each change can be evaluated independently.