Skip to content

Use paged link stores for all symbol links - #64872

Open
Jake Bailey (jakebailey) wants to merge 1 commit into
microsoft:mainfrom
jakebailey:perf/paged-symbol-links
Open

Jake Bailey (jakebailey) wants to merge 1 commit into
microsoft:mainfrom
jakebailey:perf/paged-symbol-links

Conversation

@jakebailey

Copy link
Copy Markdown
Member

Symbol links were stored in Go maps keyed by symbol pointer, so every link lookup paid for a hash and probe. Map lookups for symbol links were among the hottest leaf costs when checking large projects.

The paged store that already backs value symbol links indexes by the dense symbol ID instead, which is a couple of loads. Using it for the remaining symbol link kinds removes those map lookups, at the cost of under 1% more heap for the page tables.

--checkers 4, n=8, default GC settings:

                  │  before    │              after               │
                  │   sec/op   │   sec/op    vs base              │
Tsc/bluesky         2.826 ± 2%   2.799 ± 2%  -0.97% (p=0.015 n=8)
Tsc/sentry          11.13 ± 3%   10.86 ± 2%       ~ (p=0.083 n=8)
Tsc/t3code-server   13.97 ± 2%   13.89 ± 6%       ~ (p=0.645 n=8)
geomean             7.603        7.502       -1.32%

                  │   before     │               after                │
                  │    rss-B     │    rss-B      vs base              │
Tsc/bluesky         1.201Gi ± 2%   1.203Gi ± 2%       ~ (p=0.878 n=8)
Tsc/sentry          3.647Gi ± 9%   3.535Gi ± 6%       ~ (p=0.328 n=8)
Tsc/t3code-server   2.883Gi ± 4%   2.877Gi ± 3%       ~ (p=0.574 n=8)
geomean             2.328Gi        2.304Gi       -1.05%

                  │   before     │               after                │
                  │    heap-B    │    heap-B     vs base              │
Tsc/bluesky         934.8Mi ± 0%   934.8Mi ± 0%       ~ (p=0.798 n=8)
Tsc/sentry          2.583Gi ± 0%   2.603Gi ± 0%  +0.78% (p=0.000 n=8)
Tsc/t3code-server   2.295Gi ± 0%   2.312Gi ± 0%  +0.71% (p=0.000 n=8)
geomean             1.756Gi        1.765Gi       +0.50%

This is pretty small; want to check the real perf suite.

Symbol links were stored in Go maps keyed by symbol pointer, so every
link lookup paid for a hash and probe. Map lookups for symbol links
were among the hottest leaf costs when checking large projects.

The paged store that already backs value symbol links indexes by the
dense symbol ID instead, which is a couple of loads. Using it for the
remaining symbol link kinds removes those map lookups, at the cost of
under 1% more heap for the page tables.

--checkers 4, n=8, default GC settings:

                  │  before    │              after               │
                  │   sec/op   │   sec/op    vs base              │
Tsc/bluesky         2.826 ± 2%   2.799 ± 2%  -0.97% (p=0.015 n=8)
Tsc/sentry          11.13 ± 3%   10.86 ± 2%       ~ (p=0.083 n=8)
Tsc/t3code-server   13.97 ± 2%   13.89 ± 6%       ~ (p=0.645 n=8)
geomean             7.603        7.502       -1.32%

                  │   before     │               after                │
                  │    rss-B     │    rss-B      vs base              │
Tsc/bluesky         1.201Gi ± 2%   1.203Gi ± 2%       ~ (p=0.878 n=8)
Tsc/sentry          3.647Gi ± 9%   3.535Gi ± 6%       ~ (p=0.328 n=8)
Tsc/t3code-server   2.883Gi ± 4%   2.877Gi ± 3%       ~ (p=0.574 n=8)
geomean             2.328Gi        2.304Gi       -1.05%

                  │   before     │               after                │
                  │    heap-B    │    heap-B     vs base              │
Tsc/bluesky         934.8Mi ± 0%   934.8Mi ± 0%       ~ (p=0.798 n=8)
Tsc/sentry          2.583Gi ± 0%   2.603Gi ± 0%  +0.78% (p=0.000 n=8)
Tsc/t3code-server   2.295Gi ± 0%   2.312Gi ± 0%  +0.71% (p=0.000 n=8)
geomean             1.756Gi        1.765Gi       +0.50%
Copilot AI balanced review requested due to automatic review settings October 19, 2026 17:46
@github-project-automation github-project-automation Bot moved this to Not started in PR Backlog Oct 19, 2026
@typescript-automation typescript-automation Bot added the For Uncommitted Bug PR for untriaged, rejected, closed or missing bug label Oct 19, 2026
@jakebailey

Copy link
Copy Markdown
Member Author

TypeScript Bot (@typescript-bot) perf test this faster

@typescript-automation

typescript-automation Bot commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

Starting jobs; this comment will be updated as builds start and complete.

Command Status Results
perf test this faster ✅ Started 👀 Results

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 migration consistently reuses the existing store implementation, with no blocking issues identified.

No open issues 🎉

What changed in this PR

Replaces the checker’s remaining map-backed symbol links with existing ID-indexed paged stores to reduce lookup overhead.

Changes:

  • Migrates all remaining symbol-link stores to symbolLinkStore.
  • Renames the reverse-mapped store and updates its callers.
File Description
tsc/​internal/​checker/​nodebuilderimpl.go Updates reverse-mapped store references.
tsc/​internal/​checker/​inference.go Updates reverse-mapped link access.
tsc/​internal/​checker/​emitsupport.go Updates reverse-mapped lookup during emit.
tsc/​internal/​checker/​checker.go Converts remaining symbol-link stores to paged storage.

Review effort: Balanced

@typescript-automation

Copy link
Copy Markdown
Contributor

Jake Bailey (@jakebailey)
The results of the perf run you requested are in!

Here they are:

tsc

Comparison Report - baseline..pr
Metric baseline pr Delta Best Worst p-value
Compiler-Unions - native
Errors 41 41 ~ ~ ~ p=1.000 n=12
Symbols 115,276 115,276 ~ ~ ~ p=1.000 n=12
Types 79,613 79,613 ~ ~ ~ p=1.000 n=12
Memory Used 113,504k (± 0.07%) 116,422k (± 0.07%) +2,918k (+ 2.57%) 116,260k 116,742k p=0.000 n=12
Memory Allocs 2,212,539 (± 0.01%) 2,213,871 (± 0.01%) +1,332 (+ 0.06%) 2,213,420 2,214,176 p=0.000 n=12
Config Time 0.000s 0.000s ~ ~ ~ p=1.000 n=12
Parse Time 0.048s (± 4.42%) 0.048s (± 4.24%) ~ 0.043s 0.052s p=0.759 n=12
Bind Time 0.017s (± 9.74%) 0.017s (±10.11%) ~ 0.013s 0.021s p=0.856 n=12
Check Time 0.566s (± 1.02%) 0.560s (± 0.74%) ~ 0.552s 0.573s p=0.057 n=12
Emit Time 0.327s (± 3.20%) 0.325s (± 2.41%) ~ 0.306s 0.345s p=0.766 n=12
Total Time 0.967s (± 1.04%) 0.958s (± 0.79%) ~ 0.940s 0.980s p=0.139 n=12
angular-1 - native
Errors 3 3 ~ ~ ~ p=1.000 n=12
Symbols 846,750 (± 0.07%) 846,918 (± 0.11%) ~ 844,123 848,753 p=0.671 n=12
Types 247,033 (± 0.00%) 247,032 (± 0.00%) ~ 247,030 247,040 p=0.128 n=12
Memory Used 596,235k (± 0.02%) 610,468k (± 0.02%) +14,233k (+ 2.39%) 610,157k 610,880k p=0.000 n=12
Memory Allocs 13,150,380 (± 0.10%) 13,150,732 (± 0.04%) ~ 13,143,369 13,166,383 p=0.078 n=12
Config Time 0.020s (± 1.21%) 0.020s (± 1.21%) ~ 0.020s 0.021s p=1.000 n=12
Parse Time 0.281s (± 1.83%) 0.284s (± 2.91%) ~ 0.267s 0.310s p=0.745 n=12
Bind Time 0.100s (±13.47%) 0.109s (±13.79%) ~ 0.072s 0.142s p=0.433 n=12
Check Time 0s 0s ~ ~ ~ p=1.000 n=12
Emit Time 1.857s (± 1.73%) 1.853s (± 1.22%) ~ 1.801s 1.902s p=0.856 n=12
Total Time 2.279s (± 1.53%) 2.288s (± 1.17%) ~ 2.217s 2.334s p=0.755 n=12
mui-docs - native
Errors 11,405 11,405 ~ ~ ~ p=1.000 n=12
Symbols 4,331,983 4,331,983 ~ ~ ~ p=1.000 n=12
Types 1,370,520 1,370,520 ~ ~ ~ p=1.000 n=12
Memory Used 2,623,124k (± 0.05%) 2,621,707k (± 0.04%) ~ 2,618,717k 2,625,807k p=0.114 n=12
Memory Allocs 27,698,596 (± 0.09%) 27,713,426 (± 0.08%) ~ 27,638,158 27,782,235 p=0.078 n=12
Config Time 0.020s (± 1.60%) 0.020s (± 1.59%) ~ 0.020s 0.021s p=1.000 n=12
Parse Time 0.585s (± 2.33%) 0.580s (± 2.00%) ~ 0.533s 0.600s p=0.943 n=12
Bind Time 0.003s (±10.34%) 0.003s (±23.37%) ~ 0.002s 0.006s p=1.000 n=12
Check Time 8.658s (± 0.56%) 8.474s (± 0.20%) -0.184s (- 2.12%) 8.403s 8.516s p=0.000 n=12
Emit Time 0.673s (±11.75%) 0.677s (±10.62%) ~ 0.499s 0.793s p=0.682 n=12
Total Time 10.875s (± 0.77%) 10.699s (± 0.69%) -0.176s (- 1.62%) 10.476s 10.806s p=0.006 n=12
strada-build-src - native
Errors 0 0 ~ ~ ~ p=1.000 n=12
Symbols 1,388,680 1,388,680 ~ ~ ~ p=1.000 n=12
Types 441,862 441,862 ~ ~ ~ p=1.000 n=12
Memory Used 1,311,668k (± 0.76%) 1,365,141k (± 0.44%) 🔻+53,473k (+ 4.08%) 1,348,695k 1,383,809k p=0.000 n=12
Memory Allocs 78,181,622 (± 0.16%) 78,292,707 (± 0.08%) ~ 78,073,114 78,416,940 p=0.242 n=12
Config Time 0.005s (±10.88%) 0.004s (±12.82%) ~ 0.003s 0.006s p=0.735 n=12
Parse Time 0.311s (± 1.95%) 0.308s (± 2.31%) ~ 0.290s 0.327s p=0.579 n=12
Bind Time 0.000s 0.000s (±217.90%) ~ 0.000s 0.001s p=1.000 n=12
Check Time 1.996s (± 0.57%) 2.005s (± 0.59%) ~ 1.976s 2.032s p=0.183 n=12
Emit Time 0.354s (± 3.13%) 0.348s (± 2.57%) ~ 0.328s 0.381s p=0.224 n=12
Total Time 23.745s (± 0.32%) 23.768s (± 0.58%) ~ 23.362s 24.059s p=0.671 n=12
strada-compiler - native
Errors 0 0 ~ ~ ~ p=1.000 n=12
Symbols 334,953 334,953 ~ ~ ~ p=1.000 n=12
Types 197,616 197,616 ~ ~ ~ p=1.000 n=12
Memory Used 247,545k (± 0.03%) 254,943k (± 0.04%) +7,398k (+ 2.99%) 254,650k 255,128k p=0.000 n=12
Memory Allocs 4,329,829 (± 0.01%) 4,332,920 (± 0.01%) +3,091 (+ 0.07%) 4,332,173 4,334,014 p=0.000 n=12
Config Time 0.001s 0.001s ~ ~ ~ p=1.000 n=12
Parse Time 0.108s (± 3.12%) 0.112s (± 5.44%) ~ 0.095s 0.129s p=0.224 n=12
Bind Time 0.000s 0.000s ~ ~ ~ p=1.000 n=12
Check Time 0.960s (± 0.66%) 0.951s (± 0.57%) ~ 0.939s 0.965s p=0.071 n=12
Emit Time 0.153s (± 6.45%) 0.154s (± 4.73%) ~ 0.139s 0.178s p=0.831 n=12
Total Time 1.276s (± 0.72%) 1.275s (± 0.75%) ~ 1.254s 1.300s p=0.832 n=12
ts-pre-modules - native
Errors 87 87 ~ ~ ~ p=1.000 n=12
Symbols 303,834 303,834 ~ ~ ~ p=1.000 n=12
Types 181,663 181,663 ~ ~ ~ p=1.000 n=12
Memory Used 215,258k (± 0.02%) 221,610k (± 0.02%) +6,352k (+ 2.95%) 221,482k 221,707k p=0.000 n=12
Memory Allocs 1,401,702 (± 0.02%) 1,404,753 (± 0.02%) +3,051 (+ 0.22%) 1,404,205 1,405,177 p=0.000 n=12
Config Time 0.000s 0.000s ~ ~ ~ p=1.000 n=12
Parse Time 0.078s (± 4.45%) 0.077s (± 3.54%) ~ 0.067s 0.083s p=0.876 n=12
Bind Time 0.034s (± 8.08%) 0.033s (± 9.81%) ~ 0.024s 0.042s p=0.853 n=12
Check Time 0.618s (± 0.91%) 0.616s (± 1.18%) ~ 0.604s 0.638s p=0.369 n=12
Emit Time 0.000s 0.000s ~ ~ ~ p=1.000 n=12
Total Time 0.742s (± 0.65%) 0.738s (± 0.72%) ~ 0.726s 0.756s p=0.297 n=12
vscode - native
Errors 396 396 ~ ~ ~ p=1.000 n=12
Symbols 12,386,876 12,386,876 ~ ~ ~ p=1.000 n=12
Types 4,049,733 4,049,733 ~ ~ ~ p=1.000 n=12
Memory Used 5,821,013k (± 0.01%) 6,036,307k (± 0.01%) +215,294k (+ 3.70%) 6,034,005k 6,038,067k p=0.000 n=12
Memory Allocs 59,187,953 (± 0.01%) 59,292,258 (± 0.02%) +104,305 (+ 0.18%) 59,279,296 59,331,163 p=0.000 n=12
Config Time 0.077s (± 0.53%) 0.076s (± 0.43%) ~ 0.075s 0.077s p=0.051 n=12
Parse Time 1.811s (± 1.95%) 1.815s (± 2.28%) ~ 1.719s 1.934s p=0.899 n=12
Bind Time 0.700s (±11.97%) 0.698s (±12.55%) ~ 0.519s 0.930s p=0.887 n=12
Check Time 15.559s (± 0.90%) 15.435s (± 0.97%) ~ 15.085s 15.768s p=0.599 n=12
Emit Time 5.740s (± 6.99%) 5.237s (± 7.71%) ~ 4.563s 6.230s p=0.101 n=12
Total Time 23.982s (± 1.31%) 23.353s (± 1.46%) -0.629s (- 2.62%) 22.754s 24.217s p=0.010 n=12
webpack - native
Errors 598 598 ~ ~ ~ p=1.000 n=12
Symbols 1,398,302 1,398,302 ~ ~ ~ p=1.000 n=12
Types 670,900 670,900 ~ ~ ~ p=1.000 n=12
Memory Used 885,743k (± 0.02%) 901,174k (± 0.01%) +15,431k (+ 1.74%) 900,756k 901,468k p=0.000 n=12
Memory Allocs 6,927,047 (± 0.02%) 6,933,691 (± 0.01%) +6,645 (+ 0.10%) 6,932,285 6,935,472 p=0.000 n=12
Config Time 0.009s 0.009s ~ ~ ~ p=1.000 n=12
Parse Time 0.316s (± 3.02%) 0.319s (± 3.79%) ~ 0.289s 0.347s p=0.701 n=12
Bind Time 0.077s (± 4.32%) 0.080s (±14.26%) ~ 0.071s 0.137s p=0.478 n=12
Check Time 2.964s (± 0.24%) 2.920s (± 0.41%) -0.043s (- 1.46%) 2.875s 2.963s p=0.000 n=12
Emit Time 0.000s 0.000s ~ ~ ~ p=1.000 n=12
Total Time 3.402s (± 0.32%) 3.365s (± 0.40%) -0.037s (- 1.09%) 3.331s 3.399s p=0.000 n=12
xstate-main - native
Errors 0 0 ~ ~ ~ p=1.000 n=12
Symbols 1,060,810 1,060,810 ~ ~ ~ p=1.000 n=12
Types 389,671 389,671 ~ ~ ~ p=1.000 n=12
Memory Used 471,725k (± 0.02%) 487,105k (± 0.03%) +15,380k (+ 3.26%) 486,824k 487,440k p=0.000 n=12
Memory Allocs 4,218,847 (± 0.07%) 4,227,523 (± 0.09%) +8,676 (+ 0.21%) 4,219,900 4,238,220 p=0.000 n=12
Config Time 0.003s (±11.61%) 0.003s (± 6.23%) ~ 0.002s 0.003s p=0.317 n=12
Parse Time 0.135s (± 2.99%) 0.134s (± 3.91%) ~ 0.125s 0.151s p=0.680 n=12
Bind Time 0.045s (±18.15%) 0.048s (±14.71%) ~ 0.034s 0.068s p=0.465 n=12
Check Time 1.103s (± 1.20%) 1.083s (± 0.60%) -0.020s (- 1.81%) 1.063s 1.095s p=0.009 n=12
Emit Time 0.000s 0.000s ~ ~ ~ p=1.000 n=12
Total Time 1.291s (± 0.95%) 1.276s (± 0.80%) -0.016s (- 1.22%) 1.246s 1.294s p=0.043 n=12
System info unknown
Hosts
  • native
Scenarios
  • Compiler-Unions - native
  • angular-1 - native
  • mui-docs - native
  • strada-build-src - native
  • strada-compiler - native
  • ts-pre-modules - native
  • vscode - native
  • webpack - native
  • xstate-main - native
Benchmark Name Iterations
Current pr 12
Baseline baseline 12

Developer Information:

Download Benchmarks

This branch has not been deployed

No deployments
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: Not started

Development

Successfully merging this pull request may close these issues.

2 participants