Performance
This guide covers performance optimization strategies for the Privacy Boost iOS SDK. The native binary is small enough that bundle size is rarely the bottleneck — the costs to manage are SDK init, proof generation, balance refresh frequency, and main-thread hygiene.SDK Lifecycle
One Instance Per Process
PrivacyBoost holds a JWT, identity keys, and an internal note cache. Initialize it once and hold it in a long-lived owner — usually an @MainActor singleton or an environment object.
Defer Init Until First Use
If your app has flows that don’t touch the privacy pool (onboarding, marketing screens), defer SDK construction until the first gated route. The Rust core does some setup work on first call — keep it off the cold-start path.Off the Main Thread
All SDK operations areasync throws. Run them via Task { ... } or .task { ... } modifiers, never on the main run loop. A misplaced try await inside a synchronous function will block the actor it’s called on; let SwiftUI’s structured concurrency schedule it.
Balance Refresh
Don’t Poll From Every Screen
getBalance(tokenAddress:) and getAllBalances() hit the network. Centralize refreshes through a single observable store and let screens subscribe.
Refresh on Foreground, Not on a Timer
Repeated background polling drains battery. Refresh onscenePhase == .active and after operations that change balances:
Coalesce Concurrent Refreshes
If multiple views hit refresh simultaneously, deduplicate so only one network call happens:Network
Parallelize Independent Reads
Sequential awaits serialize unnecessarily. Useasync let:
Page History — Don’t Fetch It All
Pass a smalllimit and use the returned cursor for pagination instead of asking for the full history at once:
Memory
Drop Heavy Caches When Backgrounded
If your app stays in the background long enough to receive a memory warning, the SDK’s internal state is the second-largest consumer after image caches. Clear non-identity state on.didReceiveMemoryWarning or scene-phase transitions.
Don’t Hold Transaction Arrays in @State
For long histories, store an IdentifiedArray keyed by txHash and flush old entries beyond the visible window. SwiftUI re-diffs @State arrays on every change.
Operation Timing
Wrap SDK calls to observe timing in development:MXMetricManager) in production to surface slow operations as histograms rather than print statements.
What the SDK Already Optimizes
Things you do not need to layer on top:- Note cache — the SDK caches unspent notes locally and only refetches new merkle tree leaves.
- Merkle tree pruning — proven nodes are kept; the rest are pruned.
- JWT reuse —
clearSession()keeps identity keys so the nextauthenticate()is fast.
Best Practices Summary
- One SDK instance per process — hold it in a long-lived owner.
- Defer SDK init until the first privacy-pool screen.
- All operations on a
Task— never on the main run loop. - Refresh balances on foreground and after writes, not on a timer.
- Deduplicate concurrent refreshes through an actor.
- Parallelize independent reads with
async let. - Page transaction history; don’t fetch it all.
- Use
clearSession()overlogout()when re-auth is expected soon.