From 85621045eb4de77e6ec400110449faac0dcbb136 Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Fri, 8 Dec 2023 01:18:58 +0000 Subject: [PATCH 1/2] chore: improve each block fast-path heuristic --- .changeset/slow-chefs-dream.md | 5 ++++ .../3-transform/client/visitors/template.js | 24 +++++++++---------- 2 files changed, 17 insertions(+), 12 deletions(-) create mode 100644 .changeset/slow-chefs-dream.md diff --git a/.changeset/slow-chefs-dream.md b/.changeset/slow-chefs-dream.md new file mode 100644 index 000000000000..9cd0de887b31 --- /dev/null +++ b/.changeset/slow-chefs-dream.md @@ -0,0 +1,5 @@ +--- +'svelte': patch +--- + +chore: improve each block fast-path heuristic diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/template.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/template.js index 1330141a8e43..741afa100844 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/template.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/template.js @@ -2137,11 +2137,10 @@ export const template_visitors = { } // The runtime needs to know what kind of each block this is in order to optimize for the - // immutable + key==entry case. In that case, the item doesn't need to be reactive, because - // the array as a whole is immutable, so if something changes, it either has to recreate the - // array or use nested reactivity through runes. - // TODO this feels a bit "hidden performance boost"-style, investigate if there's a way - // to make this apply in more cases + // key === item (we avoid extra allocations). In that case, the item doesn't need to be reactive. + // We can guarnatee this by knowing that in order for the item of the each block to change, they + // would need to mutate the key/item directly in the array. Given that in runes mode we use === + // equality, we can apply a fast-path (as long as the index isn't reactive). let each_type = 0; if ( @@ -2149,21 +2148,22 @@ export const template_visitors = { (node.key.type !== 'Identifier' || !node.index || node.key.name !== node.index) ) { each_type |= EACH_KEYED; + // If there's a destructuring, then we likely need the generated $$index + if (node.index || node.context.type !== 'Identifier') { + each_type |= EACH_INDEX_REACTIVE; + } if ( + context.state.analysis.runes && node.key.type === 'Identifier' && node.context.type === 'Identifier' && node.context.name === node.key.name && - context.state.options.immutable + (each_type & EACH_INDEX_REACTIVE) === 0 ) { - // Fast-path + // Fast-path for when the key === item each_item_is_reactive = false; } else { each_type |= EACH_ITEM_REACTIVE; } - // If there's a destructuring, then we likely need the generated $$index - if (node.index || node.context.type !== 'Identifier') { - each_type |= EACH_INDEX_REACTIVE; - } } else { each_type |= EACH_ITEM_REACTIVE; } @@ -2289,7 +2289,7 @@ export const template_visitors = { ) : b.literal(null); const key_function = - node.key && (each_type & 1) /* EACH_ITEM_REACTIVE */ !== 0 + node.key && ((each_type & EACH_ITEM_REACTIVE) !== 0 || context.state.options.dev) ? b.arrow( [node.context.type === 'Identifier' ? node.context : b.id('$$item')], b.block( From 16d0d85e4ab357b7b7b545781f5fb27c17faef08 Mon Sep 17 00:00:00 2001 From: Dominic Gannaway Date: Fri, 8 Dec 2023 01:20:44 +0000 Subject: [PATCH 2/2] chore: improve each block fast-path heuristic --- .../src/compiler/phases/3-transform/client/visitors/template.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/svelte/src/compiler/phases/3-transform/client/visitors/template.js b/packages/svelte/src/compiler/phases/3-transform/client/visitors/template.js index 741afa100844..dc420fc805cc 100644 --- a/packages/svelte/src/compiler/phases/3-transform/client/visitors/template.js +++ b/packages/svelte/src/compiler/phases/3-transform/client/visitors/template.js @@ -2138,7 +2138,7 @@ export const template_visitors = { // The runtime needs to know what kind of each block this is in order to optimize for the // key === item (we avoid extra allocations). In that case, the item doesn't need to be reactive. - // We can guarnatee this by knowing that in order for the item of the each block to change, they + // We can guarantee this by knowing that in order for the item of the each block to change, they // would need to mutate the key/item directly in the array. Given that in runes mode we use === // equality, we can apply a fast-path (as long as the index isn't reactive). let each_type = 0;