Grand Diomande Research · Full HTML Reader

Algorithm Performance Specifications

**Document ID:** ALGO-PERF-001 **Version:** 1.0.0-DRAFT **Created:** 2026-01-04 **Purpose:** Define performance requirements and benchmarks for all core algorithms **Parent Document:** [04-Algorithms/README.md](./README.md) **Related Documents:** - [Visit-Sequencing.md](./Visit-Sequencing.md) - [Route-Optimization.md](./Route-Optimization.md) - [Delivery-Optimization.md](./Delivery-Optimization.md) - [Decision-Logic.md](./Decision-Logic.md)

Agents That Account for Themselves proposal experiment writeup candidate score 26 .md

Full Public Reader

Algorithm Performance Specifications

Document ID: ALGO-PERF-001
Version: 1.0.0-DRAFT
Created: 2026-01-04
Purpose: Define performance requirements and benchmarks for all core algorithms
Parent Document: [04-Algorithms/README.md](./README.md)
Related Documents:
- [Visit-Sequencing.md](./Visit-Sequencing.md)
- [Route-Optimization.md](./Route-Optimization.md)
- [Delivery-Optimization.md](./Delivery-Optimization.md)
- [Decision-Logic.md](./Decision-Logic.md)

---

Table of Contents

1. [Overview](#1-overview)
2. [Global Performance Requirements](#2-global-performance-requirements)
3. [Visit Sequencing Performance](#3-visit-sequencing-performance)
4. [Route Optimization Performance](#4-route-optimization-performance)
5. [Delivery Optimization Performance](#5-delivery-optimization-performance)
6. [Decision Logic Performance](#6-decision-logic-performance)
7. [Network Performance](#7-network-performance)
8. [UI Rendering Performance](#8-ui-rendering-performance)
9. [Memory Performance](#9-memory-performance)
10. [Battery Performance](#10-battery-performance)
11. [Offline Performance](#11-offline-performance)
12. [Swift App Parity Benchmarks](#12-swift-app-parity-benchmarks)
13. [Performance Testing Strategy](#13-performance-testing-strategy)
14. [Performance Degradation Triggers](#14-performance-degradation-triggers)
15. [Optimization Priorities](#15-optimization-priorities)

---

1. Overview

1.1 Purpose

This document defines measurable, falsifiable performance requirements for all algorithms in the Milk Men Expo migration. Performance is a critical success criterion (EM-P-001 through EM-P-004) and must meet or exceed the Swift app baseline.

1.2 Performance Philosophy

User-Centric Performance:
- Perceived performance > raw speed
- Instant feedback (optimistic UI) > blocking operations
- Progressive loading > all-or-nothing
- Graceful degradation > hard failures

Asymmetric Performance Targets:
- Interactive operations (tap, scroll): <16ms (60 FPS)
- User-initiated operations (button press): <100ms perceived response
- Background operations (sync): No user-facing latency
- Network-dependent operations: Optimistic UI + background fetch

1.3 Performance Measurement Context

All performance measurements assume:
- Device: iPhone 12 or newer (baseline)
- Network: 4G LTE (10 Mbps download, 5 Mbps upload, 50ms latency)
- Battery: >20
- Data Set: Typical organization (500 locations, 50 routes, 10 agents)
- App State: Warm start (not first launch)

---

2. Global Performance Requirements

2.1 App Launch Performance

MetricTargetMeasurement PointValidation
Cold Start<3sTap icon → First interactive screenTime to Interactive (TTI)
Warm Start<1sBackground → ForegroundResume to interactive
Hot Start<500msKilled → Relaunch (cached)Cache hit TTI

Baseline: Swift app cold start = 2.1s (measured on iPhone 12)

2.2 Navigation Performance

MetricTargetMeasurement PointValidation
Screen Transition<300msTap → New screen visibleAnimation complete
Modal Presentation<200msTap → Modal visibleFade-in complete
Tab Switch<100msTap tab → Content visibleState restored
Back Navigation<150msTap back → Previous screenUnmount + remount

2.3 Data Loading Performance

MetricTargetMeasurement PointValidation
Initial Data Load<2sLogin → Dashboard data visibleFirst paint with data
Incremental Load<500msScroll → Next page loadedPagination fetch
Pull-to-Refresh<1sPull → New data visibleRefresh complete
Search Query<300msKeystroke → Results updateDebounced search

---

3. Visit Sequencing Performance

3.1 Visit Calculation Performance

Function: `calculateNextVisitDate(location: Location): Date | null`

Input SizeTime ComplexityTarget LatencyMax Latency
Single locationO(1)<1ms<5ms
100 locations (batch)O(n)<50ms<100ms
1000 locations (batch)O(n)<300ms<500ms

Rationale: Visit date calculation is simple arithmetic (date addition) with conditional logic. Should be near-instant.

Validation:

typescript
describe('Visit Calculation Performance', () => {
  it('calculates next visit for single location in <1ms', () => {
    const start = performance.now()
    const result = calculateNextVisitDate(testLocation)
    const duration = performance.now() - start
    expect(duration).toBeLessThan(1)
  })

  it('calculates next visit for 100 locations in <50ms', () => {
    const locations = generateTestLocations(100)
    const start = performance.now()
    locations.forEach(loc => calculateNextVisitDate(loc))
    const duration = performance.now() - start
    expect(duration).toBeLessThan(50)
  })
})

3.2 Overdue Follow-Ups Query Performance

Function: `getOverdueFollowUps(agentId: string, today: Date): Location[]`

Database SizeQuery ComplexityTarget LatencyMax Latency
100 locationsO(n log n)<10ms<20ms
500 locationsO(n log n)<30ms<50ms
2000 locationsO(n log n)<100ms<200ms

Database Optimization:
- Index on `assigned_agent_id`
- Index on `next_visit_due_date`
- Index on `stage` (exclude 'lost' and 'partner')
- Composite index on `(assigned_agent_id, next_visit_due_date, stage)`

WatermelonDB Query:

typescript
const overdueLocations = await database.collections
  .get<Location>('locations')
  .query(
    Q.where('assigned_agent_id', agentId),
    Q.where('next_visit_due_date', Q.lte(today)),
    Q.where('stage', Q.notEq('lost')),
    Q.where('is_partner', false),
    Q.sortBy('next_visit_due_date', Q.asc)
  )
  .fetch()

Validation: Use WatermelonDB's `.experimentalMeasurePerformance()` to log query time.

3.3 Visit State Machine Transition Performance

Function: `transitionVisitState(location: Location, outcome: VisitOutcome): Location`

OperationTime ComplexityTarget LatencyMax Latency
Visit 1 → Visit 2O(1)<5ms<10ms
Visit 2 → Visit 3O(1)<5ms<10ms
Visit 3 → PartnerO(1) + DB write<50ms<100ms

Rationale: State transitions are simple field updates. Database write dominates latency.

---

4. Route Optimization Performance

4.1 Clustering Performance

Function: `clusterNearbyLocations(stops: Stop[], threshold: number): Cluster[]`

Input Size (Stops)Time ComplexityTarget LatencyMax Latency
5 stopsO(n²)<1ms<5ms
10 stopsO(n²)<5ms<10ms
20 stopsO(n²)<20ms<50ms
50 stopsO(n²)<100ms<200ms

Algorithm: Nested loop comparing all pairs → O(n²)

Optimization: Use spatial indexing (quadtree or R-tree) if n > 50 → O(n log n)

4.2 VIP Scoring Performance

Function: `calculateVIPScore(location: Location, today: Date): number`

Input SizeTime ComplexityTarget LatencyMax Latency
Single locationO(1)<1ms<2ms
100 locationsO(n)<50ms<100ms
500 locationsO(n)<200ms<300ms

Rationale: Simple arithmetic with conditionals. Should be near-instant.

4.3 Nearest Neighbor TSP Performance

Function: `nearestNeighborTSP(clusters: Cluster[], start: Location): Cluster[]`

Input Size (Clusters)Time ComplexityTarget LatencyMax Latency
5 clustersO(n²)<1ms<5ms
10 clustersO(n²)<10ms<20ms
20 clustersO(n²)<50ms<100ms
50 clustersO(n²)<300ms<500ms

Algorithm: Greedy nearest neighbor → O(n²)

4.4 2-Opt Improvement Performance

Function: `twoOptImprovement(route: Cluster[]): Cluster[]`

Input Size (Clusters)Time ComplexityTarget LatencyMax LatencyIterations
5 clustersO(n³)<5ms<10ms~10
10 clustersO(n³)<50ms<100ms~20
20 clustersO(n³)<300ms<500ms~30
50 clustersO(n³)<2s<5s~50

Algorithm: Iterative edge swap → O(n³) worst case, but early termination typical

Time Limit: 5 seconds absolute maximum (fallback to nearest neighbor if exceeded)

4.5 Complete Route Optimization Performance

Function: `optimizeRoute(input: RouteOptimizationInput): Promise<OptimizedRoute>`

End-to-End Latency Targets:

Input Size (Stops)ClustersTarget LatencyMax LatencyBaseline (Swift)
5 stops1-2<50ms<100ms42ms
10 stops2-4<200ms<500ms156ms
20 stops4-8<1s<2s890ms
50 stops8-15<3s<5s2.8s
100 stops15-25<8s<10s7.2s

Breakdown (20 stops example):

Stage 1: Clustering (20 stops) → 30ms
Stage 2: VIP Scoring (20 stops) → 10ms
Stage 3a: Nearest Neighbor (8 clusters) → 50ms
Stage 3b: 2-Opt (8 clusters) → 300ms
Stage 4: Time Feasibility → 50ms
Stage 5: Directions API (7 segments) → 500ms (network)
---
Total: ~940ms (within 1s target)

Performance Optimization Techniques:
1. Early termination in 2-Opt: Stop if no improvement after 5 iterations
2. Parallel scoring: Use Promise.all() for VIP scoring (if n > 50)
3. Lazy directions: Fetch polylines only when route is finalized
4. Caching: Cache distance matrix between clusters (TTL: 1 hour)

4.6 Haversine Distance Performance

Function: `haversineDistance(from: Coordinate, to: Coordinate): number`

Input SizeTime ComplexityTarget LatencyMax Latency
Single calculationO(1)<0.1ms<0.5ms
100 calculationsO(n)<10ms<20ms
10,000 calculations (n²)O(n²)<500ms<1s

Rationale: Pure math (sin, cos, sqrt). Should be near-instant.

---

5. Delivery Optimization Performance

5.1 Bin Packing Performance

Function: `assignDeliveriesToVehicles(deliveries: DeliveryStop[], vehicles: Vehicle[]): Map<string, DeliveryStop[]>`

Algorithm: First-Fit Decreasing (FFD)

Input Size (Deliveries)VehiclesTime ComplexityTarget LatencyMax Latency
10 deliveries1O(n log n)<5ms<10ms
50 deliveries2-3O(n log n)<30ms<50ms
100 deliveries3-5O(n log n)<100ms<200ms
500 deliveries5-10O(n log n)<500ms<1s

Breakdown:
- Sort deliveries by box count (descending): O(n log n)
- Iterate and assign to first vehicle with capacity: O(n × v) where v is vehicle count

5.2 Vehicle Route Optimization Performance

Function: `optimizeVehicleRoute(vehicle: Vehicle, deliveries: DeliveryStop[], warehouse: Location): DeliveryStop[]`

Same as Route Optimization Section 4.5, but with additional time window validation.

Input Size (Deliveries)Target LatencyMax Latency
5 deliveries<100ms<200ms
10 deliveries<500ms<1s
20 deliveries<2s<3s
50 deliveries<5s<8s

5.3 Time Window Validation Performance

Function: `validateTimeWindows(route: DeliveryStop[], startTime: Date): boolean`

Input Size (Stops)Time ComplexityTarget LatencyMax Latency
5 stopsO(n)<1ms<5ms
20 stopsO(n)<5ms<10ms
50 stopsO(n)<20ms<50ms

Rationale: Linear scan with date arithmetic. Should be near-instant.

5.4 Complete Delivery Optimization Performance

Function: `optimizeDeliveryRoutes(input: DeliveryOptimizationInput): Promise<DeliveryRouteOutput>`

End-to-End Latency Targets:

Input Size (Deliveries)VehiclesTarget LatencyMax LatencyBaseline (Swift)
10 deliveries1<500ms<1s420ms
50 deliveries2-3<3s<5s2.6s
100 deliveries3-5<8s<12s7.1s
500 deliveries5-10<30s<45s28s

Breakdown (50 deliveries, 2 vehicles):

Step 1: Bin Packing (50 deliveries) → 30ms
Step 2a: Vehicle 1 Route (25 stops) → 2s
Step 2b: Vehicle 2 Route (25 stops) → 2s (parallel)
Step 3: Calculate totals → 10ms
Step 4: Directions API (50 segments) → 1.5s (network)
---
Total: ~3.5s (within 5s target)

---

6. Decision Logic Performance

6.1 Should Visit Today Performance

Function: `shouldVisitToday(location: Location, agent: Agent, today: Date): VisitDecision`

Input SizeTime ComplexityTarget LatencyMax Latency
Single locationO(1)<1ms<5ms
100 locations (batch)O(n)<50ms<100ms
500 locations (batch)O(n)<200ms<300ms

Rationale: Simple conditional logic with date arithmetic.

6.2 Get Candidate Locations Performance

Function: `getCandidateLocations(agentId: string, today: Date): Promise<Location[]>`

Database Query Performance:

Database SizeResult Set SizeTarget LatencyMax Latency
100 locations10-20 candidates<20ms<50ms
500 locations30-50 candidates<50ms<100ms
2000 locations50-100 candidates<150ms<300ms

Query Optimization:
- Index on `assigned_agent_id`
- Index on `stage` (exclude 'lost')
- Index on `next_visit_due_date`
- Composite index on `(assigned_agent_id, stage, next_visit_due_date)`

6.3 Priority Ranking Performance

Function: `rankLocationsByPriority(locations: Location[], today: Date): Location[]`

Input SizeTime ComplexityTarget LatencyMax Latency
10 locationsO(n log n)<5ms<10ms
50 locationsO(n log n)<30ms<50ms
100 locationsO(n log n)<80ms<150ms

Algorithm: Calculate VIP score for each location, then sort → O(n + n log n) = O(n log n)

---

7. Network Performance

7.1 Supabase Query Performance

Query TypeExampleTarget LatencyMax LatencyTimeout
Simple SelectGet user by ID<100ms<300ms5s
Filtered SelectGet locations by org<200ms<500ms10s
Join QueryGet locations with agents<300ms<800ms10s
InsertCreate location<150ms<400ms5s
UpdateUpdate location<150ms<400ms5s
DeleteDelete location<100ms<300ms5s
Batch Insert100 locations<1s<3s30s

Network Assumptions: 4G LTE (50ms base latency + query time)

7.2 Edge Function Performance

FunctionPurposeTarget LatencyMax LatencyTimeout
google-places-searchSearch businesses<1s<3s10s
google-places-detailsGet place details<800ms<2s10s
generate-invite-codeCreate invite<200ms<500ms5s
enrich-locationEnrich with Places data<2s<5s15s

7.3 Sync Performance

OperationData SizeTarget LatencyMax LatencyTimeout
Pull (Incremental)10 changed records<500ms<1s30s
Pull (Full)500 records<3s<8s60s
Push (Small)1-5 changes<300ms<800ms10s
Push (Medium)10-50 changes<1s<3s30s
Push (Large)50-200 changes<5s<10s60s

Optimization Techniques:
1. Delta sync: Only fetch changes since last sync (timestamp-based)
2. Batch operations: Group inserts/updates into single transaction
3. Compression: Gzip request/response bodies
4. Pagination: Limit to 100 records per request

7.4 Google Maps Directions API Performance

Request TypeWaypointsTarget LatencyMax LatencyTimeout
Single Route2 (origin + destination)<500ms<1s10s
Multi-Stop5 waypoints<1s<2s15s
Multi-Stop10 waypoints<2s<4s20s
Multi-Stop25 waypoints (max)<4s<8s30s

Rate Limits: 50 requests per second (Directions API quota)

Optimization:
- Batch waypoints into single request (max 25 waypoints)
- Cache responses for 1 hour (routes don't change frequently)
- Use Haversine for estimation, Directions API for final route

---

8. UI Rendering Performance

8.1 List Rendering Performance

Component: `FlatList` (React Native virtualized list)

List SizeVisible ItemsTarget FPSTarget Frame TimeMax Jank
100 items10-1560 FPS<16ms<3 dropped frames
500 items10-1560 FPS<16ms<5 dropped frames
2000 items10-1560 FPS<16ms<10 dropped frames

Optimization Techniques:
1. Virtualization: Only render visible items + small buffer
2. Memoization: React.memo() on list item components
3. Key extraction: Use stable keys (location.id, not index)
4. getItemLayout: Pre-calculate item heights for instant scrolling
5. removeClippedSubviews: Unmount off-screen items (Android)

Validation:

typescript
import { performance } from 'perf_hooks'

const measureScrollPerformance = () => {
  const frames: number[] = []
  let lastTime = performance.now()

  const onScroll = () => {
    const now = performance.now()
    const frameTime = now - lastTime
    frames.push(frameTime)
    lastTime = now
  }

  // Measure for 3 seconds
  setTimeout(() => {
    const avgFrameTime = frames.reduce((a, b) => a + b, 0) / frames.length
    const droppedFrames = frames.filter(t => t > 16).length
    console.log(`Avg frame time: ${avgFrameTime}ms, Dropped: ${droppedFrames}`)
  }, 3000)
}

8.2 Map Rendering Performance

Component: `MapView` (react-native-maps)

Marker CountClustersTarget FPSTarget Frame TimeMax Jank
10 markers060 FPS<16ms0
50 markers5-1060 FPS<16ms<3
100 markers10-2060 FPS<16ms<5
500 markers20-5060 FPS<16ms<10

Optimization Techniques:
1. Clustering: Use react-native-maps-super-cluster for 100+ markers
2. Marker reuse: Reuse marker components, don't recreate on pan/zoom
3. Custom markers: Use native images, not complex React components
4. Lazy loading: Load markers only in visible region
5. Debounced region change: Wait for map to settle before updating markers

Pan/Zoom Performance:
- Pan gesture: 60 FPS (no lag)
- Pinch zoom: 60 FPS (smooth scaling)
- Marker tap: <100ms response time

8.3 Form Input Performance

Component: `TextInput` (React Native)

MetricTargetValidation
Keystroke latency<16msNo visible lag
Debounced validation300msValidation triggers after typing stops
Auto-save1s after last editOptimistic UI + background save

Optimization:
- Controlled inputs with `useState` (not Redux for every keystroke)
- Debounced validation (not on every keystroke)
- Optimistic UI (show save success immediately, sync in background)

8.4 Image Loading Performance

Component: `FastImage` (react-native-fast-image)

Image SizeSourceTarget Load TimeMax Load Time
Thumbnail (100x100)Local cache<50ms<100ms
Thumbnail (100x100)Network<500ms<1s
Full image (800x600)Local cache<100ms<200ms
Full image (800x600)Network<2s<5s

Optimization:
1. Progressive loading: Show thumbnail → full image
2. Lazy loading: Load images only when scrolled into view
3. Image caching: react-native-fast-image with disk cache
4. Image resizing: Serve appropriate sizes from backend (don't download 4K for 100px thumbnail)

---

9. Memory Performance

9.1 Memory Usage Targets

App StateTarget MemoryMax MemoryBaseline (Swift)
Idle (Dashboard)<80 MB<120 MB72 MB
Locations List (500)<100 MB<150 MB95 MB
Map (100 markers)<120 MB<180 MB110 MB
Route Optimization<150 MB<200 MB138 MB
Background<50 MB<80 MB45 MB

Validation: Use Xcode Instruments (Allocations, Leaks)

9.2 Memory Leak Detection

Zero tolerance for memory leaks.

Common leak sources in React Native:
1. Event listeners not cleaned up
2. Timers (setTimeout, setInterval) not cleared
3. Subscriptions (WatermelonDB, Supabase) not unsubscribed
4. Navigation listeners not removed

Validation:

typescript
useEffect(() => {
  const subscription = database.collections
    .get<Location>('locations')
    .query()
    .observe()
    .subscribe(locations => {
      setLocations(locations)
    })

  return () => {
    subscription.unsubscribe() // CRITICAL: Cleanup
  }
}, [])

9.3 Image Memory Management

Targets:

ScenarioTargetMaxLeak Check
100 thumbnails loaded<30 MB<50 MBNo growth after unmount
10 full images loaded<20 MB<40 MBNo growth after unmount

Optimization:
- FastImage with cache eviction policy (max 100 images, LRU)
- Clear cache on low memory warning
- Unmount images when scrolled far out of view

---

10. Battery Performance

10.1 Battery Drain Targets

ScenarioDurationTarget Battery DrainMax DrainBaseline (Swift)
Idle (app in background)1 hour<1
Active use (browsing)1 hour<8
GPS tracking (route)1 hour<15
Sync (background)5 minutes<0.5

Validation: Use Xcode Instruments (Energy Log)

10.2 Battery Optimization Techniques

1. Reduce GPS accuracy when idle: Switch to "significant location change" mode
2. Batch network requests: Sync every 15 minutes, not every minute
3. Throttle background refresh: iOS Background App Refresh (max 1x per hour)
4. Avoid polling: Use push notifications, not polling for updates
5. Efficient animations: Use Reanimated (runs on UI thread), not Animated API (JS thread)

---

11. Offline Performance

11.1 Offline Operation Latency

OperationTarget LatencyMax LatencyNotes
Create location (offline)<50ms<100msWrite to WatermelonDB only
Update location (offline)<50ms<100msWrite to WatermelonDB only
Delete location (offline)<30ms<80msSoft delete (mark as deleted)
Query locations (offline)<100ms<200msQuery WatermelonDB cache
Route optimization (offline)Same as onlineSame as onlineNo network dependency

Rationale: Offline operations should feel instant since no network is involved.

11.2 Sync Performance When Coming Online

Pending ChangesTarget LatencyMax LatencyNotes
1-5 changes<1s<3sPush changes to Supabase
10-50 changes<3s<8sBatched push
50-200 changes<10s<20sMultiple batch requests
200+ changes<30s<60sBackground sync with progress indicator

User Experience:
- Show "Syncing..." indicator
- Allow continued use during sync (don't block UI)
- Show success toast when sync completes
- Show error toast if sync fails (with retry button)

---

12. Swift App Parity Benchmarks

12.1 Critical User Flows (End-to-End)

FlowSwift BaselineExpo TargetExpo MaxParity
Login → Dashboard2.8s<3s<4s
Create new location1.2s<1.5s<2s
Load location detail0.8s<1s<1.5s
Optimize route (10 stops)0.9s<1s<1.5s
Log visit check-in0.6s<0.8s<1s
Sync offline changes (10)2.1s<2.5s<3s

Parity Definition: Expo app performance is ≤ 110

12.2 Rendering Benchmarks

ScreenSwift FPSExpo Target FPSNotes
Locations List (500 items)60 FPS60 FPSVirtualized list
Map (100 markers)60 FPS60 FPSWith clustering
Dashboard (stats cards)60 FPS60 FPSSimple layout
Route Planner (dragging)60 FPS55+ FPSAcceptable drop during drag

12.3 Memory Benchmarks

ScreenSwift MemoryExpo TargetExpo Max
Dashboard72 MB<80 MB<120 MB
Locations List95 MB<100 MB<150 MB
Map110 MB<120 MB<180 MB

---

13. Performance Testing Strategy

13.1 Unit Performance Tests

Jest + Performance Timing:

typescript
describe('Algorithm Performance Tests', () => {
  it('calculates VIP score in <1ms', () => {
    const location = generateTestLocation()
    const start = performance.now()
    const score = calculateVIPScore(location, new Date())
    const duration = performance.now() - start
    expect(duration).toBeLessThan(1)
  })

  it('optimizes route (10 stops) in <1s', async () => {
    const stops = generateTestStops(10)
    const start = performance.now()
    const route = await optimizeRoute({ stops, startLocation, mode: 'driving' })
    const duration = performance.now() - start
    expect(duration).toBeLessThan(1000)
  })
})

13.2 Integration Performance Tests

Detox + Performance Monitoring:

typescript
describe('User Flow Performance', () => {
  it('loads dashboard in <3s', async () => {
    const start = Date.now()
    await element(by.id('login-button')).tap()
    await waitFor(element(by.id('dashboard'))).toBeVisible().withTimeout(5000)
    const duration = Date.now() - start
    expect(duration).toBeLessThan(3000)
  })
})

13.3 Benchmarking Suite

Automated Performance Regression Detection:

1. Baseline Measurement:
- Run performance tests on Swift app (current production)
- Record all metrics as baseline JSON file
- Store in git repo (don't allow changes without justification)

2. Continuous Benchmarking:
- Run performance tests on every PR
- Compare to baseline
- Fail CI if performance degrades >10

3. Performance Dashboard:
- Track metrics over time (chart)
- Identify trends (gradual degradation)
- Set alerts for sudden drops

13.4 Real Device Testing

Test Matrix:

DeviceiOS VersionTest ScopeFrequency
iPhone 12iOS 17Full suiteEvery PR
iPhone 14 ProiOS 18Full suiteWeekly
iPhone SE (2022)iOS 17Critical flows onlyWeekly
iPad ProiPadOS 17UI rendering onlyMonthly

Why iPhone 12? Baseline device (mid-range performance, not too new, not too old).

13.5 Performance Monitoring in Production

Metrics to Track:

1. App Launch Time: Track P50, P90, P99
2. Screen Load Time: Track per screen (Dashboard, Locations, Routes)
3. API Latency: Track Supabase query times
4. Crash Rate: Track by version, device, iOS version
5. Memory Warnings: Track low memory warnings
6. Battery Drain: Track via Xcode Organizer (aggregate data)

Tools:
- Sentry (errors, performance monitoring)
- Firebase Performance Monitoring (screen traces, network traces)
- Xcode Organizer (battery, crashes, hangs)

---

14. Performance Degradation Triggers

14.1 Red Flags (Immediate Action Required)

TriggerThresholdAction
Crash rate>1
Memory leakGrowing memory usageFix immediately
Battery drain>20
ANR (App Not Responding)>100ms main thread blockMove work to background thread
Network timeout>10s for any requestAdd retry logic, increase timeout

14.2 Yellow Flags (Investigate Soon)

TriggerThresholdAction
FPS drop<55 FPS during scrollProfile with React DevTools
Memory growth>200 MB after 30 min useCheck for leaks
Slow screen load>2s for any screenAdd loading skeleton
Slow API>1s for simple queriesAdd caching, optimize query

---

15. Optimization Priorities

15.1 Optimization Tiers

Tier 1 (Must Optimize):
- App launch time (<3s)
- Screen navigation (<300ms)
- List scrolling (60 FPS)
- Route optimization (<2s for 20 stops)

Tier 2 (Should Optimize):
- Offline sync (<3s for 10 changes)
- Map rendering (60 FPS with 100 markers)
- Form validation (<300ms)

Tier 3 (Nice to Optimize):
- Image loading (<500ms for thumbnails)
- Search query (<300ms)

15.2 Premature Optimization Avoidance

Do NOT optimize until:
1. You have measured the baseline performance
2. You have identified the bottleneck (profiling)
3. The bottleneck exceeds the performance target

"Premature optimization is the root of all evil." - Donald Knuth

Optimize iteratively:
1. Build feature (correct behavior first)
2. Measure performance
3. Identify bottleneck (if any)
4. Optimize bottleneck
5. Re-measure (confirm improvement)
6. Repeat if still below target

---

16. Revision History

VersionDateChanges
1.0.0-DRAFT2026-01-04Initial performance specifications

---

17. Appendix: Performance Testing Checklist

17.1 Pre-Release Performance Validation

Before production release, all of the following must pass:

  • [ ] App Launch: Cold start <3s (iPhone 12, iOS 17)
  • [ ] Screen Navigation: All transitions <300ms
  • [ ] List Scrolling: 60 FPS with 500 locations
  • [ ] Map Rendering: 60 FPS with 100 markers
  • [ ] Route Optimization: <1s for 10 stops, <2s for 20 stops
  • [ ] Delivery Optimization: <5s for 50 deliveries
  • [ ] Offline Operations: Create/update/delete <100ms
  • [ ] Sync Performance: <3s for 10 changes
  • [ ] Memory Usage: <150 MB during active use
  • [ ] Battery Drain: <12
  • [ ] No Memory Leaks: Memory stable after 30 min use
  • [ ] No ANRs: No main thread blocks >100ms
  • [ ] Crash Rate: <0.5

17.2 Performance Regression Checklist

Run this checklist on every PR:

  • [ ] No new blocking operations on main thread
  • [ ] No new network requests without timeout
  • [ ] No new setInterval/setTimeout without cleanup
  • [ ] No new subscriptions without unsubscribe
  • [ ] No new images without lazy loading
  • [ ] No new lists without virtualization
  • [ ] No new animations on JS thread (use Reanimated)

---

This document defines the measurable performance requirements for the Expo migration. All algorithms and UI components must meet or exceed these targets to achieve parity with the Swift app.

Promotion Decision

Attach run IDs, datasets, metrics, and reproduction commands.

Source Anchor

Milk Men/Documentation/Implementation/04-Algorithms/Performance-Specs.md

Detected Structure

Method · Evaluation · Architecture