perf: optimize parser hot paths for ~18% faster compilation#17811
Merged
Rich-Harris merged 1 commit intosveltejs:mainfrom Feb 26, 2026
Merged
perf: optimize parser hot paths for ~18% faster compilation#17811Rich-Harris merged 1 commit intosveltejs:mainfrom
Rich-Harris merged 1 commit intosveltejs:mainfrom
Conversation
🦋 Changeset detectedLatest commit: 020a683 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
0a90e01 to
1498be9
Compare
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1498be9 to
020a683
Compare
Merged
Contributor
Author
I’ll do more investigation tomorrow, i have some findings that may be very interesting |
Rich-Harris
pushed a commit
that referenced
this pull request
Feb 27, 2026
This PR was opened by the [Changesets release](https://github.com/changesets/action) GitHub action. When you're ready to do a release, you can merge this and the packages will be published to npm automatically. If you're not ready to do a release yet, that's fine, whenever you add more changesets to main, this PR will be updated. # Releases ## svelte@5.53.6 ### Patch Changes - perf: optimize parser hot paths for faster compilation ([#17811](#17811)) - fix: `SvelteMap` incorrectly handles keys with `undefined` values ([#17826](#17826)) - fix: SvelteURL `search` setter now returns the normalized value, matching native URL behavior ([#17828](#17828)) - fix: visit synthetic value node during ssr ([#17824](#17824)) - fix: always case insensitive event handlers during ssr ([#17822](#17822)) - chore: more efficient effect scheduling ([#17808](#17808)) - perf: optimize compiler analysis phase ([#17823](#17823)) - fix: skip redundant batch.apply ([#17816](#17816)) - chore: null out current_batch before committing branches ([#17809](#17809)) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
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.
Summary
Optimizes the Svelte compiler's parser phase — the hot path that runs on every file compilation during development (HMR). The changes are surgical micro-optimizations to 7 files in
packages/svelte/src/compiler/phases/1-parse/, with no architectural changes.Changes
Parser.match()—slice→startsWith: Avoids creating a new substring on every multi-char match call (called thousands of times per compilation)Parser.match_regex()—slice→ sticky flag: UseslastIndex+yflag instead of slicing the entire template string on every regex match. All 14 regex patterns passed tomatch_regex/readacross 4 files updated withyflag.Parser.allow_whitespace()/require_whitespace()— regex → charCode: Replacesregex_whitespace.test()with numeric charCode comparisons in a tight loop (called hundreds of times per compilation). Covers the full\scharacter set with a fast path for common ASCII whitespace.slice: Replaceddata += template[index++]loop (O(n²)) with tracking start position + singleslice()call (O(n))read_sequence— string concatenation →slice: Same pattern — deriverawfromtemplate.slice()inflush()instead of char-by-char concatenationis_valid_element_name()— inline regexes → module-level constants: Extracted 2 regex literals to module scopenew RegExp()→indexOf: Replacedparser.read_until(new RegExp(...))withtemplate.indexOf()for script/style closing tagsmatch_bracket—Array.includes→Set.has: Pre-computes close bracket values as aSetfor O(1) lookupsBenchmark
A benchmark script was written that:
--expose-gcParse-only results
Full compile results
Benchmarked on macOS, Node.js, Apple Silicon. The parse improvements carry through to end-to-end compile time since the parser is a significant portion of the compilation pipeline. Text-heavy templates benefit the most (up to 40% faster parse).