vscode icon indicating copy to clipboard operation
vscode copied to clipboard

Memory leak in CodeEditorWidget

Open SimonSiefke opened this issue 1 year ago • 1 comments

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

  • VS Code Version: 1.86.1
  • OS Version: Ubuntu 23.04

Steps to Reproduce:

  1. Open an empty text editor
  2. Close the text
  3. Repeat opening and closing an empty text editor several times
  4. Notice that the number of disposables increases each time

Stack Trace

Opening and closing an editor 1997 times results in 3994 disposables with this stack trace:

CodeEditorContributions._register (vscode/out/vs/base/common/lifecycle.js:400:32)
CodeEditorContributions.onAfterModelAttached (vscode/out/vs/editor/browser/widget/codeEditorContributions.js:77:18)
CodeEditorWidget.setModel (vscode/out/vs/editor/browser/widget/codeEditorWidget.js:422:33)
TextFileEditor.setInput (vscode/out/vs/workbench/contrib/files/browser/editors/textFileEditor.js:105:25)
async EditorPanes.doSetInput (vscode/out/vs/workbench/browser/parts/editor/editorPanes.js:313:17)
async EditorPanes.doOpenEditor (vscode/out/vs/workbench/browser/parts/editor/editorPanes.js:207:46)
async EditorPanes.openEditor (vscode/out/vs/workbench/browser/parts/editor/editorPanes.js:110:28)
async vscode/out/vs/workbench/browser/parts/editor/editorGroupView.js:778:69
async AnythingQuickAccessProvider.openAnything (vscode/out/vs/workbench/contrib/search/browser/anythingQuickAccess.js:775:17)

Code

// codeEditorContributions.ts
public onAfterModelAttached(): void {
	this._register(runWhenWindowIdle(getWindow(this._editor?.getDomNode()), () => {
		this._instantiateSome(EditorContributionInstantiation.AfterFirstRender);
	}, 50));
}
// codeEditorWidget.ts
public setModel(_model: ITextModel | editorCommon.IDiffEditorModel | editorCommon.IDiffEditorViewModel | null = null): void {
    // ...
	this._contributions.onAfterModelAttached();
}

When opening an editor,

  1. First the setModel function is called
  2. Then, the setModel function calls contributions.onAfterModelAttached
  3. contributions.onAfterModelAttached adds a disposable to the disposable store

When closing and opening the editor again, the same happens:

  1. First the setModel function is called
  2. Then, the setModel function calls contributions.onAfterModelAttached
  3. contributions.onAfterModelAttached adds a disposable to the disposable store again

This probably causes more and more disposables to be added in CodeEditorContributions.

Possible solution

It seems, disposing the codeEditorContributions disposable (runWhenWindowIdle) when a text editor model becomes detached might be a possible solution. That way, it would be registered when a model is attached and disposed when a model becomes detached:

// codeEditorContributions
public onAfterModelAttached(): IDisposable {
	return runWhenWindowIdle(getWindow(this._editor?.getDomNode()), () => {
		this._instantiateSome(EditorContributionInstantiation.AfterFirstRender);
	}, 50);
}
// codeEditorWidget.ts
public setModel(_model: ITextModel | editorCommon.IDiffEditorModel | editorCommon.IDiffEditorViewModel | null = null): void {
    // ...
	this._contributionsDisposable = this._contributions.onAfterModelAttached();
}

private _detachModel(): ITextModel | null {
   /// ...
	this._contributionsDisposable.dispose()
}

public override dispose(): void {
    // ...
	this._contributionsDisposable.dispose()
	super.dispose();
}

SimonSiefke avatar Feb 18 '24 17:02 SimonSiefke

Thanks for creating this issue! It looks like you may be using an old version of VS Code, the latest stable release is 1.86.2. Please try upgrading to the latest version and checking whether this issue remains.

Happy Coding!

vscodenpa avatar Feb 18 '24 17:02 vscodenpa

Thanks a lot!

hediet avatar Feb 19 '24 11:02 hediet