perf: don't use tracing overeager during dev

#17176 is a case where many sources are created and then written to (due to Svelte 4 prop mechanics), and our tracing kicked in eagerly. That combined with the excessive depth of the related stack traces slowed things down tremendously.

The fix is simple: Don't record stack traces until we've seen this source get updated for a couple of times. Additionally we now delete the `updates` map after a flush. Previously it was just an ever-growing stack trace map.
pull/17183/head
Simon Holthausen 9 months ago
parent 3b4b0adcd5
commit 83cf3df024

@ -0,0 +1,5 @@
---
'svelte': patch
---
perf: don't use tracing overeager during dev

@ -53,6 +53,7 @@ export interface Analysis {
/** @deprecated use `runes` from `state.js` instead */
runes: boolean;
immutable: boolean;
/** True if `$inspect.trace` is used */
tracing: boolean;
comments: AST.JSComment[];

@ -608,6 +608,8 @@ function flush_effects() {
var was_updating_effect = is_updating_effect;
is_flushing = true;
var source_stacks = DEV ? new Set() : null;
try {
var flush_count = 0;
set_is_updating_effect(true);
@ -643,12 +645,24 @@ function flush_effects() {
batch.process(queued_root_effects);
old_values.clear();
if (DEV) {
for (const source of batch.current.keys()) {
/** @type {Set<Source>} */ (source_stacks).add(source);
}
}
}
} finally {
is_flushing = false;
set_is_updating_effect(was_updating_effect);
last_scheduled_effect = null;
if (DEV) {
for (const source of /** @type {Set<Source>} */ (source_stacks)) {
source.updated = null;
}
}
}
}

@ -188,18 +188,26 @@ export function internal_set(source, value) {
if (DEV) {
if (tracing_mode_flag || active_effect !== null) {
const error = get_stack('updated at');
source.updated ??= new Map();
if (error !== null) {
source.updated ??= new Map();
let entry = source.updated.get(error.stack);
// For performance reasons, when not using $inspect.trace, we only start collecting stack traces
// after the same source has been updated more than 5 times in the same flush cycle.
const count = source.updated.get('')?.count ?? 0;
source.updated.set('', { error: /** @type {any} */ (null), count: count + 1 });
if (!entry) {
entry = { error, count: 0 };
source.updated.set(error.stack, entry);
}
if (tracing_mode_flag || count > 5) {
const error = get_stack('updated at');
if (error !== null) {
let entry = source.updated.get(error.stack);
entry.count++;
if (!entry) {
entry = { error, count: 0 };
source.updated.set(error.stack, entry);
}
entry.count++;
}
}
}

@ -1,5 +1,8 @@
/** True if experimental.async=true */
export let async_mode_flag = false;
/** True if we're not certain that we only have Svelte 5 code in the compilation */
export let legacy_mode_flag = false;
/** True if $inspect.trace is used */
export let tracing_mode_flag = false;
export function enable_async_mode_flag() {

Loading…
Cancel
Save