Skip to content

Possible memory leak in debounce #279177

@SimonSiefke

Description

@SimonSiefke

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

  • VS Code Version: 1.106.2
  • OS Version: Ubuntu 25.04

From #279172:

When running a task 17 times, the number of objects / functions seems to increase at these specific locations:

{
  "namedFunctionCount3": [
    {
      "count": 20,
      "delta": 17,
      "name": "ChildProcessMonitor",
      "sourceLocation": "vscode/out/vs/platform/terminal/node/childProcessMonitor.js:24:13",
      "originalLocation": "src/vs/platform/terminal/node/childProcessMonitor.ts:52:19",
      "originalName": "ChildProcessMonitor"
    },
    {
      "count": 19,
      "delta": 17,
      "name": "anonymous",
      "sourceLocation": "vscode/out/vs/base/common/decorators.js:59:34",
      "originalLocation": "src/vs/base/common/decorators.ts:83:31",
      "originalName": "debounce"
    }
  ],
  "isLeak": true
}

Debounce function:

export function debounce<T>(delay: number, reducer?: IDebounceReducer<T>, initialValueProvider?: () => T) {
	return createDecorator((fn, key) => {
		const timerKey = `$debounce$${key}`;
		const resultKey = `$debounce$result$${key}`;

		return function (this: any, ...args: any[]) {

			if (!this[resultKey]) {
				this[resultKey] = initialValueProvider ? initialValueProvider() : undefined;
			}

			clearTimeout(this[timerKey]);

			if (reducer) {
				this[resultKey] = reducer(this[resultKey], ...args);
				args = [this[resultKey]];
			}

			this[timerKey] = setTimeout(() => {
				fn.apply(this, args);
				this[resultKey] = initialValueProvider ? initialValueProvider() : undefined;
			}, delay);
		};
	});
}

Looking at the debounce function, it stores the result of the function as $debounce$result$${key}. It could be a problem if the reducer function is async and returns a promise that depends on the class, creating a sort of cyclic dependency between them which prevents garbage collection

Image

Some ideas

  • Maybe prevent storing promises in debounce function, checking if result instanceof Promise and then not storing it
  • Checking if this is a Disposable and register a function to it that clears the stored debounce results when the class instance gets diposed
  • Something else??

Metadata

Metadata

Assignees

Labels

bugIssue identified by VS Code Team member as probable bugfreeze-slow-crash-leakVS Code crashing, performance, freeze and memory leak issuesterminal-processProblems launching processes, managing ptys, exiting, process leaks, etc.

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions