mirror of https://github.com/sveltejs/svelte
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 <noreply@anthropic.com>pull/17812/head
parent
b6faa2a905
commit
1043f79d1e
@ -0,0 +1,5 @@
|
||||
---
|
||||
"svelte": patch
|
||||
---
|
||||
|
||||
perf: optimize compiler analysis phase
|
||||
Loading…
Reference in new issue