perf: deduplicate profile store instances and throttle member list derivation #253

Closed
nayan9617 wants to merge 2 commits from nayan9617/flotilla:perf/deduped-profile-throttle-members into dev
Contributor

Fixes #251

Two changes to reduce reactive invalidation pressure during space sync,
as discussed in #182.

1. deriveDedupedProfile (state.ts)

deriveProfile() called from multiple components with the same pubkey
previously created a separate reactive store instance per call site.
During a relay sync burst, each store invalidated independently — for
a space with 50 members this meant up to 50 cascading $derived
recomputations per relay message batch.

Added a module-level profileStoreCache (Map keyed by serialised args)
that returns the existing store instance for a given pubkey/relays
combination rather than creating a new one. Multiple components
rendering the same pubkey now share one subscription.

Replaced deriveProfile with deriveDedupedProfile in:

  • ProfileCircle.svelte
  • ProfileDetail.svelte
  • ProfileInfo.svelte

2. throttled(300, ...) on member list derivation

SpaceMembers.svelte and RoomMembersAdd.svelte were re-deriving the full
member list on every individual relay event arrival. Wrapped
deriveSpaceMembers(url) with throttled(300, ...) from @welshman/store,
matching the pattern already used in editor/index.ts. This batches
rapid relay sync events into a single recomputation per 300ms window.

Trade-off noted: profileStoreCache holds references indefinitely.
Acceptable given the bounded number of unique pubkeys across spaces,
but worth revisiting if memory pressure from pubkey accumulation
becomes measurable.

Fixes #251 Two changes to reduce reactive invalidation pressure during space sync, as discussed in #182. **1. deriveDedupedProfile (state.ts)** deriveProfile() called from multiple components with the same pubkey previously created a separate reactive store instance per call site. During a relay sync burst, each store invalidated independently — for a space with 50 members this meant up to 50 cascading $derived recomputations per relay message batch. Added a module-level profileStoreCache (Map keyed by serialised args) that returns the existing store instance for a given pubkey/relays combination rather than creating a new one. Multiple components rendering the same pubkey now share one subscription. Replaced deriveProfile with deriveDedupedProfile in: - ProfileCircle.svelte - ProfileDetail.svelte - ProfileInfo.svelte **2. throttled(300, ...) on member list derivation** SpaceMembers.svelte and RoomMembersAdd.svelte were re-deriving the full member list on every individual relay event arrival. Wrapped deriveSpaceMembers(url) with throttled(300, ...) from @welshman/store, matching the pattern already used in editor/index.ts. This batches rapid relay sync events into a single recomputation per 300ms window. **Trade-off noted:** profileStoreCache holds references indefinitely. Acceptable given the bounded number of unique pubkeys across spaces, but worth revisiting if memory pressure from pubkey accumulation becomes measurable.
nayan9617 added 2 commits 2026-04-30 12:04:39 +00:00
nayan9617 force-pushed perf/deduped-profile-throttle-members from 949a7a7618 to d33ed4105d 2026-04-30 12:04:39 +00:00 Compare
Owner

I don't think either of these changes actually make sense. deriveProfile is already deduplicated in welshman, and membership events shouldn't be so common that they have to be throttled.

I don't think either of these changes actually make sense. `deriveProfile` is already deduplicated in welshman, and membership events shouldn't be so common that they have to be throttled.
hodlbod closed this pull request 2026-05-04 21:08:35 +00:00

Pull request closed

Sign in to join this conversation.