aboutsummaryrefslogtreecommitdiffstats
path: root/src/ark
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-11-06 21:59:36 -0700
committerAdam Soltys <[email protected]>2026-11-06 21:59:36 -0700
commit9886d4f1f51a6f0671d68ac3ba115e02b27ed474 (patch)
tree6c516be871b4346dfb0210febfd335b5abf46c1a /src/ark
parent31c4598795932b62f5cb5a7e69088561caacb7bf (diff)
downloadcoinosv3-9886d4f1f51a6f0671d68ac3ba115e02b27ed474.tar.gz
coinosv3-9886d4f1f51a6f0671d68ac3ba115e02b27ed474.zip
The wallet paints its balance without deep-copying the whole ark state five to seven times on every launch. "Its so slow to load … I'm using the apk. Compared to Minibits or something its way slower" (a user, 2026-11-05): profiled on Adam's Pixel 9 over DevTools, a launch kept the main thread pegged for ~1.7 s, and 1.4 s of it was loadArkState — every arkStateNow() during the first render (balance, history, notices, the Spending figures) structured-cloned the stored state, ~1 MB on a wallet with deep coins, ~220 ms per copy, before the manager connected and its live state took over. ArkStore.peek() hands back the stored object itself (before the store opens, or on localStorage, the parse is kept until the key is next written); wallet.peekArkState() is loadArkState through it, with the misfiled-state repair still going through loadArkState and each object's owner decoded once; arkStateNow and arkWanted read through it — read-only, as they already were with the live ark.state. Same boot on the phone, live tab with the local build: main-thread busy over the first 4 s 3.7 s → 1.8 s, no pegged stretch. tools/ark-store-test.js: peek returns the same object, sees writes at once, and drops a kept localStorage parse on write
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Diffstat (limited to 'src/ark')
-rw-r--r--src/ark/store.js20
1 files changed, 20 insertions, 0 deletions
diff --git a/src/ark/store.js b/src/ark/store.js
index b1caa94..24d8f55 100644
--- a/src/ark/store.js
+++ b/src/ark/store.js
@@ -139,6 +139,7 @@ export class ArkStore {
}
}
this.ready = true;
+ this._parsed = null; // peeks now read the opened store
if (migrated.length) {
this.flush().then(() => { for (const k of migrated) { try { ls.removeItem(k); } catch {} } }).catch(() => {});
}
@@ -153,13 +154,32 @@ export class ArkStore {
const v = this.mem.get(key);
return v ? clone(v) : null;
}
+ // The stored object itself, not a copy — for readers that only look (the
+ // render path). get() deep-copies, and a big wallet's state is ~1 MB: on a
+ // Pixel 9 each copy took ~220 ms and the first render asked five to seven
+ // times before the manager connected, 1.4 s of every launch. Never mutate
+ // what this returns. Before the store opens (or on localStorage) the parse
+ // is kept until the key is next written.
+ peek(key) {
+ if (!this.ready || this.lsMode) {
+ const hit = this._parsed && this._parsed.get(key);
+ if (hit !== undefined) return hit;
+ let v = null;
+ try { const raw = this.ls().getItem(key); v = raw ? JSON.parse(raw) : null; } catch { v = null; }
+ (this._parsed ||= new Map()).set(key, v);
+ return v;
+ }
+ return this.mem.get(key) || null;
+ }
set(key, obj) {
+ if (this._parsed) this._parsed.delete(key);
if (!this.ready || this.lsMode) { try { this.ls().setItem(key, JSON.stringify(obj)); } catch {} return; }
this.mem.set(key, obj);
this.dirty.add(key);
this._schedule();
}
remove(key) {
+ if (this._parsed) this._parsed.delete(key);
if (!this.ready || this.lsMode) { try { this.ls().removeItem(key); } catch {} return; }
this.mem.delete(key);
this.dirty.add(key);