Problem
RoomData::enforced_banned_member_ids (ui/src/room_data.rs:598) calls the uncached MembersV1::banned_member_ids, which performs one Ed25519 verification per stored ban. On the live Freenet Official room that is 200 verifications per call.
It is called from the render path (ui/src/room_data.rs:1288), and again at :641 from is_self_enforced_banned.
Cost
Ed25519 verification in the browser's wasm32 build is in the same range as the contract's (~0.26–0.42 ms/verification measured under wasmtime at OptLevel::None; the browser figure will differ but not by orders of magnitude). At 200 bans that is plausibly tens of milliseconds per call on the render path, repeated per render.
Relationship to #548
#548 introduced BanSignatureCache for exactly this redundancy on the contract side, and MembersV1::banned_member_ids_cached is pub. The UI can take the same fix by hoisting one cache across the calls it makes per render, rather than constructing a fresh one per call (which is what the uncached entry point does internally).
Not bundled into #548 because that PR is scoped to the contract WASM and its output-identity argument; this is a pure UI render-path concern with different review surface and no migration implications.
Suggested fix
Hold a BanSignatureCache for the duration of a render pass (or memoize enforced_banned_member_ids itself against the room state's ban+member generation) and call banned_member_ids_cached. Worth checking with the conversation-render profiling already done for #458 whether this shows up measurably before optimising.
Related: #548, #422.
[AI-assisted - Claude]
Problem
RoomData::enforced_banned_member_ids(ui/src/room_data.rs:598) calls the uncachedMembersV1::banned_member_ids, which performs one Ed25519 verification per stored ban. On the live Freenet Official room that is 200 verifications per call.It is called from the render path (
ui/src/room_data.rs:1288), and again at:641fromis_self_enforced_banned.Cost
Ed25519 verification in the browser's wasm32 build is in the same range as the contract's (~0.26–0.42 ms/verification measured under wasmtime at
OptLevel::None; the browser figure will differ but not by orders of magnitude). At 200 bans that is plausibly tens of milliseconds per call on the render path, repeated per render.Relationship to #548
#548 introduced
BanSignatureCachefor exactly this redundancy on the contract side, andMembersV1::banned_member_ids_cachedispub. The UI can take the same fix by hoisting one cache across the calls it makes per render, rather than constructing a fresh one per call (which is what the uncached entry point does internally).Not bundled into #548 because that PR is scoped to the contract WASM and its output-identity argument; this is a pure UI render-path concern with different review surface and no migration implications.
Suggested fix
Hold a
BanSignatureCachefor the duration of a render pass (or memoizeenforced_banned_member_idsitself against the room state's ban+member generation) and callbanned_member_ids_cached. Worth checking with the conversation-render profiling already done for #458 whether this shows up measurably before optimising.Related: #548, #422.
[AI-assisted - Claude]