Perf: replace JSON.stringify comparisons with efficient identity checks
JSON.stringify on large store objects (ae_loc, ae_api, slct, event lists) was running on every navigation, comparing serialized strings of potentially deep objects. Replace with targeted comparators: - Root +layout.svelte: add shallow_equal() helper — O(n keys) key-by-key identity check instead of O(serialized bytes). Used for ae_api, ae_loc, and slct sync guards. - Launcher +layout.svelte: ID-list join-compare for event_location_obj_li and id_li__event_location (O(n) string vs O(n*m) stringify). Refactor liveQuery closures to be pure (data-only, no store reads/writes inside the async Dexie context where Svelte reactivity tracking is undefined). Move store sync into separate $effects that compare updated_on + id (O(1)) or ID-join (O(n)) rather than full object serialization.
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
/** @type {import('./$types').LayoutData} */
|
||||
// /** @type {import('./$types').LayoutProps} */
|
||||
|
||||
let log_lvl: number = 1;
|
||||
let log_lvl: number = 0;
|
||||
|
||||
// *** Import Svelte specific
|
||||
import { untrack } from 'svelte';
|
||||
@@ -71,6 +71,20 @@
|
||||
|
||||
let last_reload_time = 0;
|
||||
|
||||
// Shallow equality guard — avoids triggering Svelte store updates when the merged
|
||||
// object is functionally identical to the current one. Comparing JSON.stringify on
|
||||
// large objects like $ae_loc (site config, device info, flags) is expensive and
|
||||
// runs on every navigation. Key-by-key identity check is O(n keys), not O(n chars).
|
||||
function shallow_equal(a: Record<string, any>, b: Record<string, any>): boolean {
|
||||
const keys_a = Object.keys(a);
|
||||
const keys_b = Object.keys(b);
|
||||
if (keys_a.length !== keys_b.length) return false;
|
||||
for (const k of keys_a) {
|
||||
if (a[k] !== b[k]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// 1. CONSOLIDATED SYNC EFFECT (One single point of entry for store updates)
|
||||
$effect(() => {
|
||||
if (!browser || !ae_acct) return;
|
||||
@@ -83,7 +97,7 @@
|
||||
const new_api = { ...current_api, ...(ae_acct.api || {}) };
|
||||
// Deep check for JWT specifically to avoid extra triggers
|
||||
if (current_api.jwt !== $ae_loc.jwt) new_api.jwt = $ae_loc.jwt;
|
||||
if (JSON.stringify(current_api) !== JSON.stringify(new_api)) {
|
||||
if (!shallow_equal(current_api, new_api)) {
|
||||
$ae_api = new_api;
|
||||
}
|
||||
|
||||
@@ -93,13 +107,13 @@
|
||||
if (!new_loc.sys_menu) new_loc.sys_menu = { hide: false, hide_access_type: false, expand_access_type: false, hide_edit_mode: false, expand_edit_mode: false, hide_user: false, expand_user: false, hide_theme: false, expand_theme: false, hide_cfg: false, expand_cfg: false };
|
||||
if (!new_loc.debug_menu) new_loc.debug_menu = { hide: false, expand: false };
|
||||
|
||||
if (JSON.stringify(current_loc) !== JSON.stringify(new_loc)) {
|
||||
if (!shallow_equal(current_loc, new_loc)) {
|
||||
$ae_loc = new_loc;
|
||||
}
|
||||
|
||||
const current_slct = $slct;
|
||||
const new_slct = { ...current_slct, ...(ae_acct.slct || {}) };
|
||||
if (JSON.stringify(current_slct) !== JSON.stringify(new_slct)) {
|
||||
if (!shallow_equal(current_slct, new_slct)) {
|
||||
$slct = new_slct;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user