From bf409076f815bd6b58a9711e5d069d309373754d Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Wed, 22 Apr 2026 02:45:15 +0000 Subject: [PATCH 1/2] perf(engine): eliminate redundant json parsing in wasmjs localStorage cache Introduced an in-memory `manifestCache` to `LocalStorageThemeCache` on the wasmJs target. This prevents the need to decode the JSON set of keys from `window.localStorage` on every single cache read and write operation, which is a significant performance bottleneck for Kotlin/WasmJS. Also added the required `.jules/bolt.md` learning entry. Co-authored-by: himattm <6266621+himattm@users.noreply.github.com> --- .jules/bolt.md | 3 +++ .../kotlin/halogen/engine/LocalStorageThemeCache.kt | 11 ++++++++--- 2 files changed, 11 insertions(+), 3 deletions(-) create mode 100644 .jules/bolt.md diff --git a/.jules/bolt.md b/.jules/bolt.md new file mode 100644 index 0000000..9d04031 --- /dev/null +++ b/.jules/bolt.md @@ -0,0 +1,3 @@ +## 2024-04-22 - WasmJs JSON Decoding Overhead +**Learning:** JSON decoding in Kotlin Multiplatform for WasmJs targets carries significant overhead when accessing localStorage. Re-parsing the same JSON structure repeatedly (e.g., manifest keys) negatively impacts performance on Web. +**Action:** Use an in-memory cache initialized when needed (or standard memory properties) to keep a parsed copy of frequently accessed data, thus minimizing redundant `localStorage` operations and `kotlinx.serialization` parsing penalties on WasmJs targets. diff --git a/halogen-engine/src/wasmJsMain/kotlin/halogen/engine/LocalStorageThemeCache.kt b/halogen-engine/src/wasmJsMain/kotlin/halogen/engine/LocalStorageThemeCache.kt index aba1f32..198e464 100644 --- a/halogen-engine/src/wasmJsMain/kotlin/halogen/engine/LocalStorageThemeCache.kt +++ b/halogen-engine/src/wasmJsMain/kotlin/halogen/engine/LocalStorageThemeCache.kt @@ -49,18 +49,23 @@ public class LocalStorageThemeCache( private val json = Json { ignoreUnknownKeys = true } private val manifestKey = "${prefix}__keys__" + // Memory cache for manifest to avoid JSON decoding on every operation + private var manifestCache: MutableSet? = null + // ── Manifest helpers ──────────────────────────────────────────────── private fun readManifest(): MutableSet { - val raw = jsGetItem(manifestKey.toJsString())?.toString() ?: return mutableSetOf() + manifestCache?.let { return it } + val raw = jsGetItem(manifestKey.toJsString())?.toString() ?: return mutableSetOf().also { manifestCache = it } return try { - json.decodeFromString>(raw).toMutableSet() + json.decodeFromString>(raw).toMutableSet().also { manifestCache = it } } catch (_: Exception) { - mutableSetOf() + mutableSetOf().also { manifestCache = it } } } private fun writeManifest(keys: Set) { + manifestCache = keys.toMutableSet() val encoded = json.encodeToString(keys) jsSetItem(manifestKey.toJsString(), encoded.toJsString()) } From 27596d416f82def6c72d530138a30b82e700d4c1 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Wed, 22 Apr 2026 03:12:06 +0000 Subject: [PATCH 2/2] perf(engine): eliminate redundant json parsing in wasmjs localStorage cache Introduced an in-memory `manifestCache` to `LocalStorageThemeCache` on the wasmJs target. This prevents the need to decode the JSON set of keys from `window.localStorage` on every single cache read and write operation, which is a significant performance bottleneck for Kotlin/WasmJS. Also added the required `.jules/bolt.md` learning entry. Co-authored-by: himattm <6266621+himattm@users.noreply.github.com>