Shrink ast.Symbol from 96 to 80 bytes - #4786
Open
mds-ant wants to merge 1 commit into
Open
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
Moves rarely populated symbol data behind a lazily allocated box, reducing 64-bit ast.Symbol size from 96 to 80 bytes while preserving compiler and language-service behavior.
Changes:
- Adds lazy accessors for members, exports, and export symbols.
- Migrates all affected consumers to the new API.
- Adds layout and allocation tests.
Reviewed changes
Copilot reviewed 24 out of 24 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
internal/ast/symbol.go |
Introduces boxed symbol extras and accessors. |
internal/ast/utilities.go |
Updates lazy symbol-table initialization. |
internal/ast/symbol_test.go |
Tests layout and on-demand allocation. |
internal/binder/binder.go |
Migrates binder symbol access. |
internal/binder/nameresolver.go |
Migrates name-resolution access. |
internal/binder/referenceresolver.go |
Migrates export-symbol access. |
internal/checker/checker.go |
Migrates core checker access and mutation. |
internal/checker/jsx.go |
Migrates JSX symbol lookups. |
internal/checker/nodebuilder_hover.go |
Migrates hover module export access. |
internal/checker/nodebuilderimpl.go |
Migrates node-builder export access. |
internal/checker/services.go |
Migrates checker service access. |
internal/checker/symbolaccessibility.go |
Migrates accessibility lookups. |
internal/checker/utilities.go |
Migrates export-assignment lookup. |
internal/api/session.go |
Migrates symbol API responses. |
internal/execute/incremental/affectedfileshandler.go |
Migrates incremental export traversal. |
internal/ls/autoimport/extract.go |
Migrates auto-import extraction. |
internal/ls/codeactions_fixclassincorrectlyimplementsinterface.go |
Migrates class member lookup. |
internal/ls/completions.go |
Migrates completion symbol access. |
internal/ls/definition.go |
Migrates constructor lookup. |
internal/ls/findallreferences.go |
Migrates reference symbol access. |
internal/ls/hover.go |
Migrates hover export-symbol access. |
internal/ls/importTracker.go |
Migrates import tracking access. |
internal/modulespecifiers/specifiers.go |
Migrates module export lookup. |
internal/transformers/declarations/transform.go |
Migrates declaration emit lookup. |
mds-ant
force-pushed
the
perf/ast-symbol-slim
branch
from
July 29, 2026 12:32
a61b987 to
c40e6a1
Compare
Member
|
@typescript-bot perf test this |
|
@jakebailey Here they are:
tscComparison Report - baseline..pr
System info unknown
Hosts
Scenarios
lspComparison Report - baseline..pr
System info unknown
Hosts
Scenarios
startupComparison Report - baseline..pr
System info unknown
Hosts
Scenarios
Developer Information: |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
jakebailey
reviewed
Jul 29, 2026
jakebailey
reviewed
Jul 29, 2026
mds-ant
force-pushed
the
perf/ast-symbol-slim
branch
from
July 29, 2026 15:59
c40e6a1 to
56d9b4c
Compare
`Members`, `Exports` and `ExportSymbol` are empty on nearly every symbol, so they now live in a lazily allocated box behind one pointer instead of three inline fields, with accessor methods for reads and writes. Setting nil never allocates a box, and `ast.GetMembers`/`GetExports` keep their create-if-nil behavior. The symbol ID stays inline because the paged link stores key symbol links by ID. No-Verification-Needed: test-only removal, product diff unchanged
mds-ant
force-pushed
the
perf/ast-symbol-slim
branch
from
July 30, 2026 08:56
56d9b4c to
649b7ff
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Context
ast.Symbolis arena-allocated, so every byte of the struct is paid once per symbol, and a full check of a large program creates millions of them (VS Code'ssrcreaches ~6.2 M). ItsMembers,ExportsandExportSymbolfields are only set on container and exported-declaration symbols. They are nil on every checker-created symbol and on most binder symbols, but they cost 24 bytes on all of them.This PR
These three fields move into a small
symbolExtrabox that is allocated the first time one of them is set to a non-nil value, referenced fromSymbolthrough a single pointer. Reads and writes go throughMembers()/SetMembers(),Exports()/SetExports()andExportSymbol()/SetExportSymbol().Memory
Typechecking the VS Code
srcproject with--noEmit(default, 4 checkers):This PR was assisted by Claude Code.