Skip to content

VS Code freezes when expanding a folder containing extremely large number of files (300M+ files) #281507

@QuantumNovice

Description

@QuantumNovice

Does this issue occur when all extensions are disabled?: Yes

  • VS Code Version: 1.106.3-bf9252a2fb45be6893dd8870c0bf37e2e1766d61-x64
  • OS Version: Windows 11-Build-26200.7309

Steps to Reproduce:

  1. Open a repo in VS Code
  2. Create or add a folder containing an extremely large number of files (mine contains ~300M)
  3. Click the folder in the Explorer
  4. The UI becomes unresponsive until the folder is collapsed

Issue Description:
When a Git repository contains a folder with a massive number of files, expanding that folder in the VS Code Explorer causes the entire UI to freeze or become unresponsive. The slowdown continues until the folder is collapsed again.

In my case the folder contains roughly 300 million files, and as soon as I click to expand it, VS Code attempts to enumerate everything and becomes sluggish. The system becomes usable again only after collapsing the folder.

Issue Behavior:

  • Clicking the folder expands it and tries to display the entire file list
  • VS Code becomes slow and UI almost freezes
  • Performance returns only when the folder is collapsed

Expected Behavior:

  • Lazily load directory entries instead of fetching all at once
  • Load in chunks or pages
  • Provide a way to jump or scroll to deeper sections without preloading all files
  • Show partial listing first and continue loading in background

Suggestion/Feature Request:
Implement incremental directory loading or virtualized list rendering for directories with extreme file counts. Showing millions of files at once is not necessary for usability.

Profiling and Functions Responsible:
I did some preliminary profiling and look into the function responsible for it.

Image

It appears to be these functions:

private async refreshAndRenderNode(node: IAsyncDataTreeNode<TInput, T>, recursive: boolean, viewStateContext?: IAsyncDataTreeViewStateContext<TInput, T>, options?: IAsyncDataTreeUpdateChildrenOptions<T>): Promise<void> {
if (this.disposables.isDisposed) {
return; // tree disposed during refresh, again (#228211)
}
await this.refreshNode(node, recursive, viewStateContext);
if (this.disposables.isDisposed) {
return; // tree disposed during refresh (#199264)
}
this.render(node, viewStateContext, options);
}

Image

private async doRefreshNode(node: IAsyncDataTreeNode<TInput, T>, recursive: boolean, viewStateContext?: IAsyncDataTreeViewStateContext<TInput, T>): Promise<IAsyncDataTreeNode<TInput, T>[]> {
node.hasChildren = !!this.dataSource.hasChildren(node.element);
let childrenPromise: Promise<Iterable<T>>;
if (!node.hasChildren) {
childrenPromise = Promise.resolve(Iterable.empty());
} else {
const children = this.doGetChildren(node);
if (isIterable(children)) {
childrenPromise = Promise.resolve(children);
} else {
const slowTimeout = timeout(800);
slowTimeout.then(() => {
node.slow = true;
this._onDidChangeNodeSlowState.fire(node);
}, _ => null);
childrenPromise = children.finally(() => slowTimeout.cancel());
}
}
try {
const children = await childrenPromise;
return this.setChildren(node, children, recursive, viewStateContext);
} catch (err) {
if (node !== this.root && this.tree.hasElement(node)) {
this.tree.collapse(node);
}
if (isCancellationError(err)) {
return [];
}
throw err;
} finally {
if (node.slow) {
node.slow = false;
this._onDidChangeNodeSlowState.fire(node);
}
}
}

Metadata

Metadata

Labels

bugIssue identified by VS Code Team member as probable bugfile-explorerExplorer widget issuesperformancetree-widgetTree widget issues

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions