Performance Runbook

Mobile Performance Runbook

This runbook defines how to profile, validate, and improve runtime performance in apps/mobile.

Scope

  • App startup and tab switching latency
  • High-frequency rerender paths (home, interview, headers)
  • Image decode/cache behavior
  • Study session startup reliability (standard and senior modes)

Current Optimizations (Implemented)

  • expo-image is used for repeated profile/avatar images with cachePolicy="memory-disk" and contentFit="cover".
  • Tab navigator is configured with:
    • lazy: true
    • freezeOnBlur: true
  • Hot paths moved from whole-store subscriptions to targeted Zustand selectors (useShallow where needed).
  • Senior mode selection is hardened to avoid non-evaluatable state-dependent prompts when profile context is missing.

Profiling Workflow

  1. Build and run a dev client (not Expo Go for realistic native behavior):
    • cd apps/mobile
    • npm run ios or npm run android
  2. Record baseline traces:
    • Cold start to first interactive screen
    • Home tab open, then switch across all tabs twice
    • Start one standard practice session and one senior session
  3. Check for:
    • JS thread stalls during tab switches
    • Excessive rerenders in home/interview components
    • Repeated image fetch/decode instead of cache hits
  4. Save trace artifacts and device metadata in PR notes.

Acceptance Targets

  • Tab switch interaction remains smooth with no visible frame drops on mid-tier Android.
  • Home screen re-renders only when selected store slices change.
  • Senior practice/exam startup never returns empty sessions when eligible senior questions exist.
  • No regression in algorithm test suites and interview API mode tests.

Native Module Roadmap (Performance-Focused)

Adopt modules only after profiling shows a measurable bottleneck.

Tier 1 (Recommended Next)

  1. react-native-mmkv
  • Why: significantly faster key-value storage than AsyncStorage for hot reads/writes.
  • Use for: frequently updated lightweight state (session metadata, cached counters).
  • Caution: requires migration strategy and encryption decision.
  1. @shopify/flash-list
  • Why: better list virtualization performance for long/complex lists.
  • Use for: large history/result feeds or dense question lists.
  • Caution: only worth adding where list rendering is an actual bottleneck.

Tier 2 (Conditional)

  1. expo-sqlite (or another SQLite wrapper)
  • Why: better structure/perf for large historical datasets than key-value storage.
  • Use for: high-volume analytics/history storage.
  • Caution: schema migrations and query abstraction overhead.
  1. @shopify/react-native-performance
  • Why: production-grade startup and interaction instrumentation.
  • Use for: objective P50/P95 monitoring in release builds.
  • Caution: adds telemetry plumbing and dashboard work.

Tier 3 (Specialized)

  1. @shopify/react-native-skia
  • Why: highly optimized custom graphics pipeline.
  • Use for: heavy custom animated canvases only.
  • Caution: avoid unless current UI requirements exceed standard RN/Reanimated capabilities.

Decision Gate Before Adding Any Module

Require all three:

  1. Measured bottleneck in profiler traces
  2. Estimated gain and owner for rollout
  3. Regression test plan (functional + performance)

Without these, keep current stack and optimize code paths first.