Repository navigation
Formatter perf improvements - #65002
Open
Wesley Wigham (weswigham) wants to merge 6 commits into
Open
Wesley Wigham (weswigham) wants to merge 6 commits into
Wesley Wigham (weswigham) wants to merge 6 commits into
Conversation
Wesley Wigham (weswigham)
requested review from
Gabriela Araujo Britto (gabritto) and
Jake Bailey (jakebailey)
and
a balanced review from Copilot
October 28, 2026 22:16
Contributor
There was a problem hiding this comment.
🔵 Needs a closer look
The unsafe, default-on SIMD paths rely on experimental Go 1.27 APIs and vector-mask layout, while AMD64/ARM64 correctness and allocation validation across SIMD/scalar builds and vector widths remains unverified.
No open issues 🎉
What changed in this PR
This PR builds on #64997 to improve formatting performance in the native TypeScript compiler and language server. It reduces allocations and repeated work, adds SIMD-assisted text scanning, and reports roughly 30% faster formatting of checker.ts.
Changes:
- Optimize trivia scanning, string escaping, line maps, and position maps with scalar and SIMD paths.
- Cache formatter line lookups and avoid redundant trivia copies.
- Add regression tests, fuzz coverage, and benchmarks; enable SIMD by default while retaining non-SIMD CI coverage.
| File | Description |
|---|---|
tsc/internal/stringutil/textscan.go |
Add shared ASCII prefix-scanning helpers. |
tsc/internal/stringutil/textscan_test.go |
Test and benchmark prefix scans. |
tsc/internal/stringutil/textscan_simd.go |
Implement SIMD prefix scanning. |
tsc/internal/stringutil/textscan_simd_test.go |
Verify SIMD mask offsets and byte order. |
tsc/internal/stringutil/textscan_scalar.go |
Provide non-SIMD scanning implementations. |
tsc/internal/scanner/scanner.go |
Accelerate trivia scanning and line-end lookup. |
tsc/internal/scanner/scanner_test.go |
Cover bulk trivia and stopping options. |
tsc/internal/scanner/lines_test.go |
Verify line-end positions across newline encodings. |
tsc/internal/printer/utilities.go |
Integrate optimized escaping and hexadecimal output. |
tsc/internal/printer/textscan_test.go |
Add escaping boundary tests, fuzzing, and benchmarks. |
tsc/internal/printer/escaping.go |
Add allocation-conscious string escaping. |
tsc/internal/printer/escaping_test.go |
Check allocations and UTF-16 escape output. |
tsc/internal/printer/escaping_reference_test.go |
Preserve an independent reference escaping implementation. |
tsc/internal/parser/parser_test.go |
Separate parsing and position-map benchmarks. |
tsc/internal/fourslash/tests/formatBulkTrivia_test.go |
Verify editor formatting with long trivia and Unicode. |
tsc/internal/format/span.go |
Use cached formatter line lookups. |
tsc/internal/format/scanner.go |
Share trivia buffers instead of cloning them. |
tsc/internal/format/scanner_test.go |
Verify saved trivia survives scanner operations. |
tsc/internal/format/rulecontext.go |
Use cached line lookups for semicolon decisions. |
tsc/internal/format/README.md |
Document benchmarking and profiling commands. |
tsc/internal/format/format_test.go |
Test bulk-trivia formatting and idempotence. |
tsc/internal/format/context.go |
Cache line starts and the last line lookup. |
tsc/internal/format/context_test.go |
Check cached lookups in both traversal directions. |
tsc/internal/format/benchmark_test.go |
Add document and editor-operation benchmarks. |
tsc/internal/core/textscan_test.go |
Test and benchmark line starts and UTF-16 lengths. |
tsc/internal/core/linestarts_simd.go |
Add SIMD line-start computation. |
tsc/internal/core/linestarts_simd_test.go |
Verify line-break mask packing. |
tsc/internal/core/linestarts_scalar.go |
Retain scalar line-start computation. |
tsc/internal/core/core.go |
Optimize line-start and UTF-16 length calculations. |
tsc/internal/ast/positionmap.go |
Skip ASCII runs when building position maps. |
tsc/internal/ast/positionmap_scan_test.go |
Test position-map boundaries and benchmark scanning. |
tools/scripts/gen/generatedFile.test.mts |
Verify SIMD defaults preserve explicit experiment settings. |
Herebyfile.mjs |
Default tasks to SIMD unless explicitly configured. |
.github/workflows/ci.yml |
Enable SIMD and add a non-SIMD test job. |
Review effort: Balanced
This branch has not been deployed
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.
This is a followup to #64997 since it sets up the SIMD build stuff - the formatting scanner is something simd should lend some benefits to, but most of the improvements here are actually just reduced allocations and repeated work and not simd-specific. This is like a 30% perf improvement for formatting
checker.ts, and about 2/3rds of that isn't simd-related.