Skip to content

Bound arena retention by bytes instead of object count - #64802

Merged
Jake Bailey (jakebailey) merged 1 commit into
jakebailey/mem/cold-type-node-signature-statefrom
jakebailey/mem/byte-sized-arena-chunks
Oct 14, 2026
Merged

Jake Bailey (jakebailey) merged 1 commit into
jakebailey/mem/cold-type-node-signature-statefrom
jakebailey/mem/byte-sized-arena-chunks

Conversation

@jakebailey

Copy link
Copy Markdown
Member

A live pointer into an arena chunk keeps the whole chunk alive, including unused capacity and dead neighbours. Fixed 256-object chunks are especially wasteful for large records.

  • Targets about 512 bytes per typed-arena chunk instead of 256 objects.
  • VS Code measurements showed 8.54% less retained heap, 10.44% less GC scanning, and 9.43% fewer instructions.
  • The tradeoff is 13.91% more allocation events.

Part of the memory optimization stack summarized in #64734.

Replaces #64786, which GitHub closed as merged when the stack was reordered.

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.

🟢 Approval recommended

The sizing logic is sound and covered by focused regression tests.

0 open findings

What changed in this PR

Bounds arena chunks by byte size to reduce retained heap and GC scanning.

Changes:

  • Caps chunks near 512 bytes while retaining the 256-element limit.
  • Adds retention, slice, and zero-sized-value tests.
File Description
tsc/​internal/​core/​arena.go Implements byte-aware arena sizing.
tsc/​internal/​core/​arena_test.go Tests retention bounds and allocation behavior.

🧠 Review effort: Balanced


💡 Add a code-review agent skill for context-aware, tailored reviews. Learn more in the docs.

@jakebailey
Jake Bailey (jakebailey) force-pushed the jakebailey/mem/byte-sized-arena-chunks branch from 609a018 to 543248f Compare October 13, 2026 21:39
@jakebailey
Jake Bailey (jakebailey) force-pushed the jakebailey/mem/byte-sized-arena-chunks branch 2 times, most recently from a3b5ac9 to f2c6548 Compare October 14, 2026 02:23
@ahejlsberg
Anders Hejlsberg (ahejlsberg) force-pushed the jakebailey/mem/byte-sized-arena-chunks branch from f2c6548 to 648889b Compare October 14, 2026 14:14
A live pointer into an arena chunk retains the entire backing
allocation, including unused capacity and unrelated dead values.
Resetting typed parser and binder arenas at every file multiplies
terminal chunk slack. Uniform 256-object chunks are especially wasteful
for large records.

Target 512 bytes per chunk before allocator rounding, preserving stable
direct pointers and exact-capacity slices. Larger contiguous slices keep
their separate allocation path. No GC settings, cross-file pooling, or
pointer decoding are introduced.

Six fresh-process interleaved VS Code comparisons against the parent
commit, using normal GC, reduce retained bytes 8.54%, scan bytes 10.44%,
allocated bytes 5.74%, and whole-process instructions 9.43%. Allocation
events rise 13.91%; wall time is inconclusive on the shared machine
(p=0.937).

Four-object chunks saved slightly more heap but raised allocation events
32.15%. A 512-byte target keeps most of the memory savings with less
than half that allocation penalty. Reusing partial parser and binder
chunks also saved memory but would couple otherwise independent file
lifetimes.

The retention regression fails with the old allocator. Mixed singleton,
slice, clone, growth, zero-size, and GC cases preserve addresses and
data. Production diagnostics and file, line, identifier, symbol, type,
and instantiation counts match exactly.

goos: linux
goarch: amd64
pkg: github.com/microsoft/TypeScript/tsc/internal/checker
cpu: Intel(R) Core(TM) i9-10900K CPU @ 3.70GHz
                   │ vscode-arena-before.txt │          vscode-arena.txt          │
                   │       retained-B        │  retained-B   vs base              │
ExternalProgram-20              3.823Gi ± 0%   3.497Gi ± 0%  -8.54% (p=0.002 n=6)

                   │ vscode-arena-before.txt │          vscode-arena.txt           │
                   │         scan-B          │    scan-B     vs base               │
ExternalProgram-20              3.418Gi ± 0%   3.062Gi ± 0%  -10.44% (p=0.002 n=6)

                   │ vscode-arena-before.txt │          vscode-arena.txt          │
                   │          B/op           │     B/op      vs base              │
ExternalProgram-20              5.442Gi ± 0%   5.130Gi ± 0%  -5.74% (p=0.002 n=6)

                   │ vscode-arena-before.txt │          vscode-arena.txt          │
                   │        allocs/op        │  allocs/op   vs base               │
ExternalProgram-20               27.36M ± 0%   31.17M ± 0%  +13.91% (p=0.002 n=6)

                        │ arena-before-instructions.txt │        arena-instructions.txt         │
                        │        instructions/op        │ instructions/op  vs base              │
ExternalInstructions-20                     300.8G ± 3%       272.5G ± 6%  -9.43% (p=0.002 n=6)
@jakebailey
Jake Bailey (jakebailey) force-pushed the jakebailey/mem/byte-sized-arena-chunks branch from 648889b to 0f77391 Compare October 14, 2026 14:17
@jakebailey
Jake Bailey (jakebailey) added this pull request to the merge queue Oct 14, 2026
Merged via the queue into main with commit e67b60e Oct 14, 2026
54 checks passed
@jakebailey
Jake Bailey (jakebailey) deleted the jakebailey/mem/byte-sized-arena-chunks branch October 14, 2026 16:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Author: Team For Uncommitted Bug PR for untriaged, rejected, closed or missing bug

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants