Commit 1043f79
perf: optimize compiler analysis phase (#17823)
## Summary
Two optimizations to the compiler's analysis phase:
- **Cache `ignore_stack` snapshots instead of `structuredClone` on every
node.** The universal `_` visitor in the analysis walk runs on every AST
node and calls `structuredClone(ignore_stack)` each time. In practice,
`svelte-ignore` comments are rare (0–5 per component), so 99%+ of nodes
deep-clone an unchanged stack. This adds a copy-on-write cache that only
re-creates the snapshot when `push_ignore`/`pop_ignore` actually change
the stack.
- **Walk the CSS stylesheet once instead of once per element.**
`prune()` was called in a loop for each element, each time doing a full
`walk()` of the stylesheet AST. This restructures the loop so the
stylesheet is walked once, and the element iteration happens inside the
`ComplexSelector` visitor.
## Benchmarks
Compiled each component 500 times (after 50 warmup iterations),
measuring average time per `compile()` call:
| Component | Before | After | Speedup |
|---|---|---|---|
| `has` (80+ CSS selectors, 12 elements) | 3.405 ms | 2.680 ms | **21%
faster** |
| `siblings-combinator-each-nested` (65 CSS rules, 15 elements) | 2.034
ms | 1.575 ms | **23% faster** |
| synthetic (100 CSS rules, 50 elements) | 10.099 ms | 4.564 ms | **55%
faster** |
The CSS pruning optimization scales with `elements × CSS rules` — the
more elements a component has, the bigger the win since we go from N
stylesheet walks down to 1. The `structuredClone` fix helps every
component regardless of CSS, eliminating ~500–2000 deep clones per
compile (one per AST node) and replacing them with 0–5 (one per
`svelte-ignore` comment).
For typical real-world components with 10–20 elements and some CSS,
expect roughly **20–30% faster compilation** in the analysis phase.
## Test plan
- [x] Full test suite passes (7329 tests, 0 failures)
- [x] CSS pruning tests pass (selector matching, scoping, unused rule
detection)
- [x] `svelte-ignore` behavior unchanged (snapshot is consumed read-only
via `.has()`/`.some()`)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
---------
Co-authored-by: Claude Opus 4.6 <[email protected]>1 parent b6faa2a commit 1043f79
4 files changed
Lines changed: 45 additions & 17 deletions
File tree
- .changeset
- packages/svelte/src/compiler
- phases/2-analyze
- css
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
Lines changed: 14 additions & 12 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
125 | 125 | | |
126 | 126 | | |
127 | 127 | | |
128 | | - | |
| 128 | + | |
129 | 129 | | |
130 | | - | |
| 130 | + | |
131 | 131 | | |
132 | 132 | | |
133 | 133 | | |
| |||
139 | 139 | | |
140 | 140 | | |
141 | 141 | | |
142 | | - | |
| 142 | + | |
| 143 | + | |
143 | 144 | | |
144 | | - | |
145 | | - | |
146 | | - | |
147 | | - | |
148 | | - | |
149 | | - | |
150 | | - | |
151 | | - | |
152 | | - | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
153 | 155 | | |
154 | 156 | | |
155 | 157 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
21 | 21 | | |
22 | 22 | | |
23 | 23 | | |
24 | | - | |
| 24 | + | |
25 | 25 | | |
26 | 26 | | |
27 | 27 | | |
| |||
134 | 134 | | |
135 | 135 | | |
136 | 136 | | |
137 | | - | |
| 137 | + | |
138 | 138 | | |
139 | 139 | | |
140 | 140 | | |
| |||
856 | 856 | | |
857 | 857 | | |
858 | 858 | | |
859 | | - | |
860 | | - | |
861 | | - | |
| 859 | + | |
862 | 860 | | |
863 | 861 | | |
864 | 862 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
82 | 82 | | |
83 | 83 | | |
84 | 84 | | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
85 | 105 | | |
86 | 106 | | |
87 | 107 | | |
88 | 108 | | |
89 | 109 | | |
90 | 110 | | |
| 111 | + | |
91 | 112 | | |
92 | 113 | | |
93 | 114 | | |
94 | 115 | | |
| 116 | + | |
95 | 117 | | |
96 | 118 | | |
97 | 119 | | |
| |||
141 | 163 | | |
142 | 164 | | |
143 | 165 | | |
| 166 | + | |
144 | 167 | | |
0 commit comments