Skip to content

Improve performance of fs operations in extension host#324070

Open
DavyLandman wants to merge 2 commits into
microsoft:mainfrom
SWAT-engineering:fix/avoid-rpc-for-activated-filesystems
Open

Improve performance of fs operations in extension host#324070
DavyLandman wants to merge 2 commits into
microsoft:mainfrom
SWAT-engineering:fix/avoid-rpc-for-activated-filesystems

Conversation

@DavyLandman

@DavyLandman DavyLandman commented Jul 2, 2026

Copy link
Copy Markdown

Context

We have an extension that was doing some heavy IO operations using the vscode.workspace.fs interface (for operations on both file and custom virtual filesystems). We noticed it was quite a bit slower than using "raw" nodejs fs/promise (readFile/readDirectory). Important to note that it was many small files in many nested directories.

During profiling we noticed more than half of the time spend idling, and this let us to inspect the code of VS Code a bit more.

Analysis

#136657 and #172345 created a fast path such that both file:/// and virtual file systems registered inside the extension host do not need to "cross" the bridge to the rendering process that often. Especially the result of the fs functions did not need to be serialized across the RPC. For large files or large directory listing, this makes quite a big impact.

However, before every FS operation, VS Code would make sure that the VFS was registered (even for the file provider) like so:

await that._proxy.$ensureActivation(uri.scheme);

in side the rendering process this would quickly terminate if there is already a provider registered, so for infrequent IO, this small call and the rpc-overhead is fine, it takes some time, like you'll have to wait for one of the next ticks to arrive before it continues, but impact not so bad.

However if you're doing a lot small IO operations (like crawling a directory with many files, and then reading them, or first calling stat on them, etc) this starts to add up.

Proposed solution

This PR introduces a small function that only sends this ensureActivation the first time, and that that does not send it anymore. As the dispose clears the map entry, I do not see why we would need to resend the activation every time.

An alternative would be to send the ensureActivation but leave the promise floating, so that we don't join the queue. I think that's less nice of a solution, but in a way it's less invasive of a change than this PR proposes.

The fast path of a "local" fs operation in the extension host would
always still invoke a function in the proxy (that would return quickly).
But with large amount of small IO, the overhead
of the rpc-calls and the await on the result was causing a 3x slowdown.
Copilot AI review requested due to automatic review settings July 2, 2026 15:21

Copilot AI 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.

Pull request overview

This PR optimizes the extension-host fast-path for vscode.workspace.fs operations by avoiding an IPC $ensureActivation(scheme) roundtrip on every shortcut file-system call once the scheme has already been activated, reducing overhead for workloads that perform many small operations.

Changes:

  • Replaces per-operation $ensureActivation calls in the shortcut path with a per-scheme activator (provider.activate()).
  • Introduces buildActivator(scheme) to memoize activation for a provider entry.
  • Extends the internal provider map entries to carry the activator function.

Comment thread src/vs/workbench/api/common/extHostFileSystemConsumer.ts Outdated
Comment thread src/vs/workbench/api/common/extHostFileSystemConsumer.ts Outdated
Comment thread src/vs/workbench/api/common/extHostFileSystemConsumer.ts
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@DavyLandman DavyLandman changed the title Avoid proxy-calls for every time we take the shortcut Improve performance of fs operations in extension host Jul 2, 2026
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.

2 participants