Repository navigation
perf: make async blocker analysis linear - #18549
Conversation
trace_references() re-created a fresh seen set for every CallExpression, so touch() re-walked the same transitive assignment graph once per call. For N calls reaching an N-deep binding chain this was O(N^2). Share one seen set per trace_references() invocation (separate sets for the writes-directed CallExpression touches and the reads-directed ReturnStatement touches) so each assignment-value expression is walked at most once, making the traversal linear. touch() only ever adds to a fixed target set, so skipping an already-seen expression never drops a binding: compiler output is byte-identical.
|
Install the latest version of pnpm add https://pkg.svelte.dev/svelte/c/79ef7d744bea869d4ef45cac5f2c0337e28f6a4eOpen in Note This PR is from a fork. A maintainer must approve approve each commit before it can be built and installed. |
🦋 Changeset detectedLatest commit: 79ef7d7 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 |
|
Thank you - though I think we can omit the new tests. |
Sure thing, done. |
dummdidumm
left a comment
There was a problem hiding this comment.
thank you!
there was another PR merged in the meantime which meant I had to add a new Set() but the cases where it's used are rare so should not affect perf.
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.56.10 ### Patch Changes - fix: preserve CSS escape sequences when printing selectors ([#18667](#18667)) - fix: parse `:nth-child(2n of.foo)` where `of` is not followed by whitespace ([#18611](#18611)) - fix: transform expressions inside labeled statements during server compilation ([#18617](#18617)) - docs: clarify that context lookup includes the current component and all ancestors ([#18581](#18581)) - fix: apply CSS custom properties with falsy values on components ([#18634](#18634)) - fix: correctly print `{#await ... catch x}` et al ([#18645](#18645)) - fix: ignore comments of Program node during migration script ([#18656](#18656)) - fix: reliably resolve append_style to its correct root ([#18614](#18614)) - fix: clean up removed capture event handlers from spread attributes ([#18618](#18618)) - fix: don't corrupt renderer type during SSR's legacy `bind:` retry loop ([#18616](#18616)) - fix: treat concise arrow function bodies as implicit returns when calculating blockers ([#18613](#18613)) - fix: give effect teardowns the value from before the first write in a flush ([#18620](#18620)) - fix: avoid double-calling a derived reference when destructuring `$derived` of another `$derived` during server-side rendering ([#18668](#18668)) - fix: preserve namespaces in CSS type selectors ([#18678](#18678)) - fix: increment private state fields through a non-`this` receiver ([#18622](#18622)) - chore: deduplicate client and server context helpers ([#18580](#18580)) - fix: release `last_propagated_event` after event propagation settles so it no longer retains the last event's target subtree ([#18569](#18569)) - fix: allow custom elements to receive async values as props ([#18661](#18661)) - fix: strip comments from inline `style` values in linear time ([#18553](#18553)) - fix: prevent declaration comments from breaking server derived references ([#18641](#18641)) - perf: make async blocker analysis scale linearly with the number of top-level references ([#18549](#18549)) - fix: preserve short-circuiting for logical assignments to private state fields ([#18594](#18594)) Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
This PR contains the following updates: | Package | Change | [Age](https://docs.renovatebot.com/merge-confidence/) | [Confidence](https://docs.renovatebot.com/merge-confidence/) | |---|---|---|---| | [svelte](https://svelte.dev) ([source](https://github.com/sveltejs/svelte/tree/HEAD/packages/svelte)) | [`5.56.9` → `5.56.10`](https://renovatebot.com/diffs/npm/svelte/5.56.9/5.56.10) |  |  | --- ### Release Notes <details> <summary>sveltejs/svelte (svelte)</summary> ### [`v5.56.10`](https://github.com/sveltejs/svelte/blob/HEAD/packages/svelte/CHANGELOG.md#55610) [Compare Source](https://github.com/sveltejs/svelte/compare/svelte@5.56.9...svelte@5.56.10) ##### Patch Changes - fix: preserve CSS escape sequences when printing selectors ([#​18667](sveltejs/svelte#18667)) - fix: parse `:nth-child(2n of.foo)` where `of` is not followed by whitespace ([#​18611](sveltejs/svelte#18611)) - fix: transform expressions inside labeled statements during server compilation ([#​18617](sveltejs/svelte#18617)) - docs: clarify that context lookup includes the current component and all ancestors ([#​18581](sveltejs/svelte#18581)) - fix: apply CSS custom properties with falsy values on components ([#​18634](sveltejs/svelte#18634)) - fix: correctly print `{#await ... catch x}` et al ([#​18645](sveltejs/svelte#18645)) - fix: ignore comments of Program node during migration script ([#​18656](sveltejs/svelte#18656)) - fix: reliably resolve append\_style to its correct root ([#​18614](sveltejs/svelte#18614)) - fix: clean up removed capture event handlers from spread attributes ([#​18618](sveltejs/svelte#18618)) - fix: don't corrupt renderer type during SSR's legacy `bind:` retry loop ([#​18616](sveltejs/svelte#18616)) - fix: treat concise arrow function bodies as implicit returns when calculating blockers ([#​18613](sveltejs/svelte#18613)) - fix: give effect teardowns the value from before the first write in a flush ([#​18620](sveltejs/svelte#18620)) - fix: avoid double-calling a derived reference when destructuring `$derived` of another `$derived` during server-side rendering ([#​18668](sveltejs/svelte#18668)) - fix: preserve namespaces in CSS type selectors ([#​18678](sveltejs/svelte#18678)) - fix: increment private state fields through a non-`this` receiver ([#​18622](sveltejs/svelte#18622)) - chore: deduplicate client and server context helpers ([#​18580](sveltejs/svelte#18580)) - fix: release `last_propagated_event` after event propagation settles so it no longer retains the last event's target subtree ([#​18569](sveltejs/svelte#18569)) - fix: allow custom elements to receive async values as props ([#​18661](sveltejs/svelte#18661)) - fix: strip comments from inline `style` values in linear time ([#​18553](sveltejs/svelte#18553)) - fix: prevent declaration comments from breaking server derived references ([#​18641](sveltejs/svelte#18641)) - perf: make async blocker analysis scale linearly with the number of top-level references ([#​18549](sveltejs/svelte#18549)) - fix: preserve short-circuiting for logical assignments to private state fields ([#​18594](sveltejs/svelte#18594)) </details> --- ### Configuration 📅 **Schedule**: (UTC) - Branch creation - At any time (no schedule defined) - Automerge - At any time (no schedule defined) 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box --- This PR has been generated by [Mend Renovate CLI](https://github.com/renovatebot/renovate). <!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiI0NC4zMS4wIiwidXBkYXRlZEluVmVyIjoiNDQuMzEuMCIsInRhcmdldEJyYW5jaCI6Im1haW4iLCJsYWJlbHMiOltdfQ==-->
##### [v5.56.10](https://github.com/sveltejs/svelte/blob/HEAD/packages/svelte/CHANGELOG.md#55610) ##### Patch Changes - fix: preserve CSS escape sequences when printing selectors ([#18667](sveltejs/svelte#18667)) - fix: parse `:nth-child(2n of.foo)` where `of` is not followed by whitespace ([#18611](sveltejs/svelte#18611)) - fix: transform expressions inside labeled statements during server compilation ([#18617](sveltejs/svelte#18617)) - docs: clarify that context lookup includes the current component and all ancestors ([#18581](sveltejs/svelte#18581)) - fix: apply CSS custom properties with falsy values on components ([#18634](sveltejs/svelte#18634)) - fix: correctly print `{#await ... catch x}` et al ([#18645](sveltejs/svelte#18645)) - fix: ignore comments of Program node during migration script ([#18656](sveltejs/svelte#18656)) - fix: reliably resolve append\_style to its correct root ([#18614](sveltejs/svelte#18614)) - fix: clean up removed capture event handlers from spread attributes ([#18618](sveltejs/svelte#18618)) - fix: don't corrupt renderer type during SSR's legacy `bind:` retry loop ([#18616](sveltejs/svelte#18616)) - fix: treat concise arrow function bodies as implicit returns when calculating blockers ([#18613](sveltejs/svelte#18613)) - fix: give effect teardowns the value from before the first write in a flush ([#18620](sveltejs/svelte#18620)) - fix: avoid double-calling a derived reference when destructuring `$derived` of another `$derived` during server-side rendering ([#18668](sveltejs/svelte#18668)) - fix: preserve namespaces in CSS type selectors ([#18678](sveltejs/svelte#18678)) - fix: increment private state fields through a non-`this` receiver ([#18622](sveltejs/svelte#18622)) - chore: deduplicate client and server context helpers ([#18580](sveltejs/svelte#18580)) - fix: release `last_propagated_event` after event propagation settles so it no longer retains the last event's target subtree ([#18569](sveltejs/svelte#18569)) - fix: allow custom elements to receive async values as props ([#18661](sveltejs/svelte#18661)) - fix: strip comments from inline `style` values in linear time ([#18553](sveltejs/svelte#18553)) - fix: prevent declaration comments from breaking server derived references ([#18641](sveltejs/svelte#18641)) - perf: make async blocker analysis scale linearly with the number of top-level references ([#18549](sveltejs/svelte#18549)) - fix: preserve short-circuiting for logical assignments to private state fields ([#18594](sveltejs/svelte#18594))
##### [v5.56.10](https://github.com/sveltejs/svelte/blob/HEAD/packages/svelte/CHANGELOG.md#55610) ##### Patch Changes - fix: preserve CSS escape sequences when printing selectors ([#18667](sveltejs/svelte#18667)) - fix: parse `:nth-child(2n of.foo)` where `of` is not followed by whitespace ([#18611](sveltejs/svelte#18611)) - fix: transform expressions inside labeled statements during server compilation ([#18617](sveltejs/svelte#18617)) - docs: clarify that context lookup includes the current component and all ancestors ([#18581](sveltejs/svelte#18581)) - fix: apply CSS custom properties with falsy values on components ([#18634](sveltejs/svelte#18634)) - fix: correctly print `{#await ... catch x}` et al ([#18645](sveltejs/svelte#18645)) - fix: ignore comments of Program node during migration script ([#18656](sveltejs/svelte#18656)) - fix: reliably resolve append\_style to its correct root ([#18614](sveltejs/svelte#18614)) - fix: clean up removed capture event handlers from spread attributes ([#18618](sveltejs/svelte#18618)) - fix: don't corrupt renderer type during SSR's legacy `bind:` retry loop ([#18616](sveltejs/svelte#18616)) - fix: treat concise arrow function bodies as implicit returns when calculating blockers ([#18613](sveltejs/svelte#18613)) - fix: give effect teardowns the value from before the first write in a flush ([#18620](sveltejs/svelte#18620)) - fix: avoid double-calling a derived reference when destructuring `$derived` of another `$derived` during server-side rendering ([#18668](sveltejs/svelte#18668)) - fix: preserve namespaces in CSS type selectors ([#18678](sveltejs/svelte#18678)) - fix: increment private state fields through a non-`this` receiver ([#18622](sveltejs/svelte#18622)) - chore: deduplicate client and server context helpers ([#18580](sveltejs/svelte#18580)) - fix: release `last_propagated_event` after event propagation settles so it no longer retains the last event's target subtree ([#18569](sveltejs/svelte#18569)) - fix: allow custom elements to receive async values as props ([#18661](sveltejs/svelte#18661)) - fix: strip comments from inline `style` values in linear time ([#18553](sveltejs/svelte#18553)) - fix: prevent declaration comments from breaking server derived references ([#18641](sveltejs/svelte#18641)) - perf: make async blocker analysis scale linearly with the number of top-level references ([#18549](sveltejs/svelte#18549)) - fix: preserve short-circuiting for logical assignments to private state fields ([#18594](sveltejs/svelte#18594))
trace_referencesrecreated a fresh seen set for every CallExpression, sotouchre-walked the same transitive assignment graph once per call. For N calls reaching an N-deep binding chain, this wasShare one seen set per trace_references invocation. Use separate sets for the write-directed CallExpression touches and the read-directed ReturnStatement touches. The shared set ensures each assignment-value expression is walked at most once, making the traversal linear.
touchonly ever adds to a fixed target set, so skipping an already-seen expression never drops a binding: compiler output is byte-identical.calculate_blockers performance
Apple M4 Max; Node 24.18.0; pnpm 10.4.0; Hyperfine 1.20.0. Each command used 3 warmups and 15 measured runs. Hyperfine timed batched compiler processes; the matching compiler-import/source-generation baseline was subtracted, then the mean was divided by the batch size.
Benchmark code and Hyperfine commands
Save as
$BASE/blocker-hyperfine.mjs:Before:
602a873b6b82bba4e6edc91b039e2f6defbe3fc4After:
ca8cb55e23cd15d626a4ca01aa5ed073a689b519Complements #18548.