Skip to content

Investigation: slow Profile-mode wallet load (post sphere-telco-test deploy 2026-06-02) #386

@vrogojin

Description

@vrogojin

Symptom

User reports: "Loading the profile takes a lot of time" on https://sphere-telco-test.dyndns.org after deploy of bundle index-B4OewTZs.js (sphere-sdk @ 96991eb on PR #385 — the identity-keys cache-only + lazy-backfill fixes).

Browser-console-visible artifacts from the same load that are already understood / not the cause:

So the slow-load symptom is a separate concern — needs profiling.

What we know about the load path

Sphere.init in Profile-mode on an existing wallet (see sphere/src/sdk/SphereProvider.tsx:607-744) does:

  1. First Sphere.init with legacy createBrowserProviders → spins up Sphere bound to legacy IndexedDB storage.
  2. runProfileMigration → reads legacy tokens, writes Profile bundle CAR to IPFS, anchors via aggregator pointer.
  3. Sphere.destroy({ force: true, reason: 'uxf-profile-swap' }).
  4. Second Sphere.init with Profile-backed providers (createBrowserProfileProvidersFromSphere) + fallbackStorage: legacyStorageForFallback → spins up Sphere bound to OrbitDB.
  5. After Sphere ready: setupIpfsSync, address discovery, send-welcome-DM.

Candidate slow-load sources (need profiler to confirm)

Candidate Source file Approx cost
First-boot Profile migration (one-time per wallet) profile/migration.ts seconds–10s+ depending on legacy data size
OrbitDB pubsub initial peer discovery (second Sphere.init) profile/orbitdb-adapter.ts ~10–30 s cold
Initial pointer-poll → aggregator → IPFS roundtrip profile/aggregator-pointer/* + profile/ipfs-client.ts 1–3 s + 2 s gateway capability probe
/sidecar/blob 404 streak before cold-cache trips at 3 misses (PR #384) profile/ipfs-client.ts:524 ~RTT × 3, then short-circuits
First Sphere.init reading legacy tokens before migration IndexedDBTokenStorageProvider depends on token count
_payments.load() reading CAR from IPFS (second init) PaymentsModule.loadProfileTokenStorage.load depends on CAR size + gateway RTT

What we need from the next reproduction

To pinpoint without guessing:

  1. DevTools → Performance record of a load, from page navigation to "balances visible". User attaches the trace OR shares a few representative User Timing measure names if the SDK already emits them.
  2. OR the screen state during the slow phase:
    • Blank page → time is before the React tree mounts.
    • Loading wallet… spinner → Sphere.init (likely Profile migration step or 2nd init's OrbitDB sync).
    • UI visible but balances/messages blank → _payments.load() reading CAR.
  3. OR observability data from existing counters in profile/profile-token-storage/flush-scheduler.ts (the incr('flushScheduler.flushToIpfs.calls') / observeMs('flushScheduler.flushToIpfs.totalMs') pair) and similar in the OrbitDB adapter — pull from sphere.metrics if exposed.

Quick instrumentation worth adding (deferred to whoever picks this up)

If the next reproduction confirms the bottleneck is in Sphere.init rather than data-fetch, add structured console.time/console.timeEnd (or performance.measure) milestones at each setInitProgress({step: ..., message: ...}) site in sphere/src/sdk/SphereProvider.tsx:656,704,736 and inside sphere-sdk/core/Sphere.ts at the boundaries of loadIdentityFromStorage, initializeModules, runProfileMigration invocation, second init start, and setupIpfsSync. That gives operator timing without needing a Performance trace.

Not in scope here

Related

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions