From 8d710765c2fda99cde4a174423959bf43f2d0a87 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Thu, 14 Aug 2025 16:08:11 -0400 Subject: [PATCH 1/7] tweak --- .../src/internal/client/reactivity/effects.js | 46 ++++++++++--------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/packages/svelte/src/internal/client/reactivity/effects.js b/packages/svelte/src/internal/client/reactivity/effects.js index 68a155503237..5e3c37cb7969 100644 --- a/packages/svelte/src/internal/client/reactivity/effects.js +++ b/packages/svelte/src/internal/client/reactivity/effects.js @@ -133,29 +133,31 @@ function create_effect(type, fn, sync, push = true) { schedule_effect(effect); } - // if an effect has no dependencies, no DOM and no teardown function, - // don't bother adding it to the effect tree - var inert = - sync && - effect.deps === null && - effect.first === null && - effect.nodes_start === null && - effect.teardown === null && - (effect.f & EFFECT_PRESERVED) === 0; - - if (!inert && push) { - if (parent !== null) { - push_effect(effect, parent); - } + if (push) { + // if an effect has no dependencies, no DOM and no teardown function, + // don't bother adding it to the effect tree + var inert = + sync && + effect.deps === null && + effect.first === null && + effect.nodes_start === null && + effect.teardown === null && + (effect.f & EFFECT_PRESERVED) === 0; + + if (!inert) { + if (parent !== null) { + push_effect(effect, parent); + } - // if we're in a derived, add the effect there too - if ( - active_reaction !== null && - (active_reaction.f & DERIVED) !== 0 && - (type & ROOT_EFFECT) === 0 - ) { - var derived = /** @type {Derived} */ (active_reaction); - (derived.effects ??= []).push(effect); + // if we're in a derived, add the effect there too + if ( + active_reaction !== null && + (active_reaction.f & DERIVED) !== 0 && + (type & ROOT_EFFECT) === 0 + ) { + var derived = /** @type {Derived} */ (active_reaction); + (derived.effects ??= []).push(effect); + } } } From d4696fd0203aa5e444971348e54b21ffa59206c2 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Thu, 14 Aug 2025 16:46:59 -0400 Subject: [PATCH 2/7] prune effects where possible --- .../src/internal/client/reactivity/effects.js | 35 ++++++++++++------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/packages/svelte/src/internal/client/reactivity/effects.js b/packages/svelte/src/internal/client/reactivity/effects.js index 5e3c37cb7969..446f57da37e5 100644 --- a/packages/svelte/src/internal/client/reactivity/effects.js +++ b/packages/svelte/src/internal/client/reactivity/effects.js @@ -134,19 +134,28 @@ function create_effect(type, fn, sync, push = true) { } if (push) { - // if an effect has no dependencies, no DOM and no teardown function, - // don't bother adding it to the effect tree - var inert = - sync && - effect.deps === null && - effect.first === null && - effect.nodes_start === null && - effect.teardown === null && - (effect.f & EFFECT_PRESERVED) === 0; - - if (!inert) { + var e = /** @type {Effect | null} */ (effect); + + // if an effect has already ran and doesn't need to be kept in the tree + // (because it won't re-run, has no DOM, and has no teardown etc) + // then we skip it and go to its child (if any) + while ( + e !== null && + e.deps === null && + e.teardown === null && + e.nodes_start === null && + (e.f & EFFECT_RAN) !== 0 && + (e.f & ROOT_EFFECT) === 0 && + (e.f & BRANCH_EFFECT) === 0 && + (e.f & EFFECT_PRESERVED) === 0 + ) { + if (e.first !== e.last) break; + e = e.first; + } + + if (e !== null) { if (parent !== null) { - push_effect(effect, parent); + push_effect(e, parent); } // if we're in a derived, add the effect there too @@ -156,7 +165,7 @@ function create_effect(type, fn, sync, push = true) { (type & ROOT_EFFECT) === 0 ) { var derived = /** @type {Derived} */ (active_reaction); - (derived.effects ??= []).push(effect); + (derived.effects ??= []).push(e); } } } From 5eaea161045ad1316a1e9d7b471f0ac18c8b03e9 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Thu, 14 Aug 2025 16:59:43 -0400 Subject: [PATCH 3/7] tweak --- packages/svelte/src/internal/client/reactivity/effects.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/svelte/src/internal/client/reactivity/effects.js b/packages/svelte/src/internal/client/reactivity/effects.js index 446f57da37e5..9b354f817339 100644 --- a/packages/svelte/src/internal/client/reactivity/effects.js +++ b/packages/svelte/src/internal/client/reactivity/effects.js @@ -139,17 +139,17 @@ function create_effect(type, fn, sync, push = true) { // if an effect has already ran and doesn't need to be kept in the tree // (because it won't re-run, has no DOM, and has no teardown etc) // then we skip it and go to its child (if any) - while ( + if ( e !== null && e.deps === null && e.teardown === null && e.nodes_start === null && + e.first === e.last && (e.f & EFFECT_RAN) !== 0 && (e.f & ROOT_EFFECT) === 0 && (e.f & BRANCH_EFFECT) === 0 && (e.f & EFFECT_PRESERVED) === 0 ) { - if (e.first !== e.last) break; e = e.first; } From 39f2bf0a7758caa5c1dc4e6116d8204ebc351a37 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Thu, 14 Aug 2025 17:05:11 -0400 Subject: [PATCH 4/7] simplify --- .../src/internal/client/reactivity/effects.js | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/packages/svelte/src/internal/client/reactivity/effects.js b/packages/svelte/src/internal/client/reactivity/effects.js index 9b354f817339..06ee9dc1d85b 100644 --- a/packages/svelte/src/internal/client/reactivity/effects.js +++ b/packages/svelte/src/internal/client/reactivity/effects.js @@ -134,20 +134,19 @@ function create_effect(type, fn, sync, push = true) { } if (push) { - var e = /** @type {Effect | null} */ (effect); + /** @type {Effect | null} */ + var e = effect; // if an effect has already ran and doesn't need to be kept in the tree // (because it won't re-run, has no DOM, and has no teardown etc) // then we skip it and go to its child (if any) if ( - e !== null && + sync && e.deps === null && e.teardown === null && e.nodes_start === null && e.first === e.last && (e.f & EFFECT_RAN) !== 0 && - (e.f & ROOT_EFFECT) === 0 && - (e.f & BRANCH_EFFECT) === 0 && (e.f & EFFECT_PRESERVED) === 0 ) { e = e.first; @@ -253,7 +252,7 @@ export function inspect_effect(fn) { */ export function effect_root(fn) { Batch.ensure(); - const effect = create_effect(ROOT_EFFECT, fn, true); + const effect = create_effect(ROOT_EFFECT | EFFECT_PRESERVED, fn, true); return () => { destroy_effect(effect); @@ -267,7 +266,7 @@ export function effect_root(fn) { */ export function component_root(fn) { Batch.ensure(); - const effect = create_effect(ROOT_EFFECT, fn, true); + const effect = create_effect(ROOT_EFFECT | EFFECT_PRESERVED, fn, true); return (options = {}) => { return new Promise((fulfil) => { @@ -386,7 +385,7 @@ export function block(fn, flags = 0) { * @param {boolean} [push] */ export function branch(fn, push = true) { - return create_effect(BRANCH_EFFECT, fn, true, push); + return create_effect(BRANCH_EFFECT | EFFECT_PRESERVED, fn, true, push); } /** From aed8f8c7b8aa5becf0890758fedc5167df530ed1 Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Thu, 14 Aug 2025 17:10:06 -0400 Subject: [PATCH 5/7] simplify --- packages/svelte/src/internal/client/reactivity/effects.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/svelte/src/internal/client/reactivity/effects.js b/packages/svelte/src/internal/client/reactivity/effects.js index 06ee9dc1d85b..33f73ad6c7fa 100644 --- a/packages/svelte/src/internal/client/reactivity/effects.js +++ b/packages/svelte/src/internal/client/reactivity/effects.js @@ -145,8 +145,7 @@ function create_effect(type, fn, sync, push = true) { e.deps === null && e.teardown === null && e.nodes_start === null && - e.first === e.last && - (e.f & EFFECT_RAN) !== 0 && + e.first === e.last && // either `null`, or a singular child (e.f & EFFECT_PRESERVED) === 0 ) { e = e.first; From 1290ab46bc89878f4da6ca09a1a85b0be370b72d Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Thu, 14 Aug 2025 17:10:38 -0400 Subject: [PATCH 6/7] changeset --- .changeset/tasty-lizards-care.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/tasty-lizards-care.md diff --git a/.changeset/tasty-lizards-care.md b/.changeset/tasty-lizards-care.md new file mode 100644 index 000000000000..b6aff07ffb1f --- /dev/null +++ b/.changeset/tasty-lizards-care.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +perf: prune effects without dependencies From 514699a41c1c595df81683d17e36eb95636c046c Mon Sep 17 00:00:00 2001 From: Rich Harris Date: Thu, 14 Aug 2025 20:08:02 -0400 Subject: [PATCH 7/7] reset parent if necessary --- packages/svelte/src/internal/client/reactivity/effects.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/svelte/src/internal/client/reactivity/effects.js b/packages/svelte/src/internal/client/reactivity/effects.js index 33f73ad6c7fa..324bd3c233ad 100644 --- a/packages/svelte/src/internal/client/reactivity/effects.js +++ b/packages/svelte/src/internal/client/reactivity/effects.js @@ -152,6 +152,8 @@ function create_effect(type, fn, sync, push = true) { } if (e !== null) { + e.parent = parent; + if (parent !== null) { push_effect(e, parent); }