microsoft / microsoft/vscode

Renderer UndoRedoService._editStacks & ResourceEditStack._past grows unboundedly and leaks memory over long sessions

Open
#326,812 1 comment 0 reactions 1 assignee Claimed by @hediet View on GitHub
Dominant language
TypeScript
Stars
193k
Forks
42.4k
PR merge metrics
PR metrics pending

Description

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

- VS Code Version: 1.107.1 (Node.js 22.21.1, V8 14.2.231.27-electron.0)
- OS Version: macOS (Darwin arm64 24.6.0)

Steps to Reproduce:

1. Generate a large file:
dd if=/dev/zero bs=1M count=500 | tr '\0' 'A' > /tmp/test_large.log
2. Open this file in VS Code.
3. In the file, perform the following actions:
a. `Ctrl+A` (or `Cmd+A` on macOS) to select all.
b. Type any character (e.g. `"x"`) — this produces a `TextChange.oldText` of roughly 500 MB.
c. `Ctrl+Z` (or `Cmd+Z`) to undo.
d. Type another character.
e. Repeat steps a–d 10–20 times.
4. Observe: the renderer process memory keeps climbing, and each select-all-and-replace cycle adds roughly 1 GB of retained memory (`oldText` + `newText`).

Expected:
`UndoRedoService._editStacks` stays bounded — entries for closed resources are released, and per-resource `_past` / `_future` stacks are trimmed by the configured element-count / total-size limits, so total retained memory stays flat over time.

Actual:
A heap snapshot from a long-running session shows `UndoRedoService._editStacks` alone retaining **~6.24 GB (36% of the renderer heap)**. Concrete evidence from the snapshot:

- `_editStacks: Map` retained size: **6,548,231 kB**.
- One specific `ResourceEditStack` entry (key `12`, allocation site `workbench/browser/parts/titlebar/titlebarPart.ts:361:1`) alone retains **6,545,726 kB** — i.e., a single resource is responsible for essentially all the growth.
- That entry's `_past: Array` has **at least 1,924 elements** (indices [1909]..[1924]+ visible, each `_Fe` element retaining 83–99 MB, monotonically decreasing with age).
- Each `_Fe` element retains a `KF` (`editor/common/core/edits/lineEdit.ts:342:35`) → `model: n_` (`tokens/treeSitter/tokenStore.ts`) → `_buffer: rAe` (`pieceTreeTextBuffer`) → `_pieceTree: z$s` → `_buffers: Array` chain, with `_buffers` retaining ~1.67 GB across many `D8` buffer objects created from `editor/common/model/textModelSearch.ts:312:40`.
Image

Any suggestions on how to address this would be greatly appreciated.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.