From fdaf7137139540d2f8de50b2a42d6ff3c036328b Mon Sep 17 00:00:00 2001 From: Adam Soltys Date: Sun, 11 Oct 2026 19:51:45 -0700 Subject: Feed: a wheel scroll through a loading feed no longer stutters on a laptop. The phone was fine (its scroll is the compositor's) but the desktop's wheel coast is driven from the main thread, so every long task froze it, and a feed that was still loading ran dozens of them: each ready post went in through its own admitFeed → holdScroll → full render (200–450 ms apiece; a Popular switch did 49 in a few seconds, one of them 1.3 s). Inside those renders the window's list getter — run on every scroll frame too — filtered every note through the mute/spam/report checks, and each check re-derived the login identity (two parses of the stored state plus a bech32 encode): 11 s of a 2-minute profile. Now ready posts are admitted together, one render per 120 ms, and while the reader is moving the page the batch waits for a quiet moment (up to 1.5 s); nostrLoginIdentity keeps its answer for 250 ms (dropped by its own saves, a signer change or another wallet's key), npubOf is memoized, modOn reads the cached messages state, the foreign-language guess is remembered per post, and the window list is reused between renders. Measured on Adam's dev tab (tools/feed-scroll-jank.js: real CDP wheel notches, chip clicks mid-load, rAF frame gaps, long tasks, a CPU profile that names each busy stretch): stalled time during a switch 1.9–2.5 s → 0–83 ms, no frame over 50 ms on the wheel path, main thread busy 33% → 17%; settled scrolling was already clean. feed-streaming's "tap reveals the oldest ready new post" fails on the previous commit too. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Fable 5.1 --- src/nostr.js | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'src/nostr.js') diff --git a/src/nostr.js b/src/nostr.js index e414d57..b76e865 100644 --- a/src/nostr.js +++ b/src/nostr.js @@ -466,7 +466,16 @@ export function parseNostrPubkey(input) { return null; } // An npub or 64-hex nostr pubkey → hex, or null if it isn't one. -export function npubOf(pkHex) { try { return npubEncode(pkHex); } catch { return null; } } +// Memoized: the feed asks for the reader's npub thousands of times while it +// filters rows, and bech32 encoding was the top self time of a scroll. +const npubMemo = new Map(); +export function npubOf(pkHex) { + if (npubMemo.has(pkHex)) return npubMemo.get(pkHex); + let v = null; try { v = npubEncode(pkHex); } catch {} + if (npubMemo.size > 4000) npubMemo.clear(); + npubMemo.set(pkHex, v); + return v; +} // An event reference other clients can resolve: the id plus who wrote it, so // a quote can be fetched even by someone who doesn't have it yet. export function neventOf(id, author) { try { return neventEncode({ id, author }); } catch { return null; } } -- cgit v1.2.3