Skip to content

Perf: slow chat load at login with many rooms/history #143

Description

@mjkatgithub

Planning

  • Milestone: TBD (proposal: next phase)
  • Priority: P1 (proposal — affects every login)
  • Size: L (investigation + several optimizations; may split)
  • Estimate: 5 SP (proposal — split if it grows)
  • Epic: none (standalone)

Context / Observation

The app feels sluggish on login, in dev and in the live build. During the
#136 E2E work the browser sessions were noticeably snappier than the real
app. The likely difference: E2E rooms hold almost no messages and there
are far fewer rooms, so the initial Matrix sync and first render are
cheap. With a real account (many rooms + long history) the initial
/sync payload and client-side processing are much heavier.

Hypotheses (to confirm with metrics)

  • startClient({ initialSyncLimit: 50 }) pulls up to 50 timeline events
    per room on first sync (see useMatrixClient.ts, both login and
    initializeClientFromStoredSession). With many rooms this dominates
    first-sync time and payload size.
  • Room members are likely fetched eagerly (no lazy-load members filter),
    inflating the /sync response.
  • refreshRooms() recomputes getRooms() + unread + lobby hierarchy on
    every sync-prepared/refresh; could be costly and not incremental.
  • Rust crypto + IndexedDB initialization runs before startClient;
    measure its share of time-to-interactive.

Goal

Reduce time-to-interactive at login (and session restore) for accounts
with many rooms and long history, without breaking chat features or the
E2E suite.

Scope

  • Establish a baseline: instrument and measure login → first-interactive,
    /sync payload size, and main-thread blocking on a representative
    heavy account vs. the light E2E account.
  • Evaluate lowering initialSyncLimit for first paint with on-demand
    backfill of older messages (timeline already paginates).
  • Enable lazy-loading of room members (filtered /sync) and load members
    on demand (room open / member panel).
  • Make refreshRooms() incremental/debounced instead of full recompute on
    every sync.
  • Measure crypto/IndexedDB init cost; defer non-critical crypto work where
    safe.
  • Note (future): sliding sync / simplified sync if the homeserver and SDK
    support it.

Acceptance criteria

  • Documented before/after metrics on a representative heavy account
    (time-to-interactive, /sync payload size, main-thread blocking).
  • Measurable improvement in time-to-interactive at login (target set
    after baseline, e.g. ≥ 30 %).
  • No regression in chat behavior (timeline, unread, spaces, lobby).
  • Full non-@wip E2E suite stays green.

Test checklist

Manual

  • Heavy-account login timing before/after (record numbers).
  • Verify older-message backfill still works on scroll.
  • Verify member list loads correctly when opening a room.

Automated

  • Unit/integration for any changed loading/refresh logic.
  • npm run test:e2e green.

Branch

feature/login-initial-load-perf

Notes

Files of interest: app/composables/useMatrixClient.ts (startClient +
sync), app/pages/chat.vue (refreshRooms, sync watchers),
app/composables/useRoomUnread.ts, app/composables/chat/. Origin:
observation during #136.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    Status
    Backlog

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions