Mobile performance is measured differently than web performance. Users notice jank at 16ms, battery drain over hours, and data usage over cellular connections. The constraints are harder — limited CPU, limited memory, limited bandwidth, limited battery — and the expectations are higher because native apps are supposed to feel instant.
| Metric | Target | Measurement Tool |
|---|
| Cold start time | < 1 second | iOS: Instruments, Android: adb |
| Warm start time | < 500ms | Time to interactive |
| Frame rate | 60 fps (16.6ms per frame) | Core Animation, GPU rendering |
| Memory usage | < 200MB typical | Instruments, Android Profiler |
| Battery impact | < 5% per hour active use | Energy Diagnostics, Battery Historian |
| App size | < 50MB download (ideally < 20MB) | App Store Connect, Play Console |
| Network data | Minimize redundant transfers | Charles Proxy, Network Monitor |
Startup Optimization
| Phase | What Happens | Optimization |
|---|
| Process creation | OS launches process (10-50ms) | Cannot optimize |
| Runtime initialization | Load frameworks, initialize runtime (50-200ms) | Reduce linked frameworks, lazy load |
| App initialization | AppDelegate/Application setup (50-500ms) | Defer non-critical work |
| First frame | Layout + render first screen (100-300ms) | Pre-computed layouts, skeleton screens |
| Data loading | Network/cache → populate UI (200ms-2s) | Cache first, background refresh |
Techniques
| Technique | iOS | Android |
|---|
| Lazy initialization | Defer service setup to first use | Lazy properties, WorkManager for deferred |
| Module loading | Reduce linked dylibs | Reduce dex file count |
| Skeleton screens | Show placeholder UI immediately | ShimmerLayout, Compose placeholders |
| Pre-warm data | Cache critical data on disk | Room/DataStore pre-population |
| Reduce main thread work | Move initialization off main | Move work to background dispatchers |
Memory Management
| Issue | Symptom | Diagnostic | Fix |
|---|
| Memory leak | Growing memory over time | Instruments Leaks, LeakCanary | Fix retain cycles, clear references |
| Image memory | Large memory spike on image load | Memory graph debugger | Downscale images, use disk cache |
| Cache unbounded | Memory grows with data | Memory monitor | LRU cache with size limit |
| View controller leak | Memory grows on navigation | Instruments Allocations | Weak references in closures/callbacks |
| Retained fragments | Android memory growth | Android Profiler | Proper fragment lifecycle |
Image Memory Rules
| Image Size | Raw Memory | Optimization |
|---|
| 4000×3000 (12MP photo) | ~48 MB | Downscale to display size |
| 1080×1920 (phone screen) | ~8 MB | Acceptable for full-screen |
| 100×100 (avatar) | ~40 KB | Cache in memory |
Battery Optimization
| Battery Drain Source | Impact | Mitigation |
|---|
| GPS (continuous) | Very high | Request only when needed, significant location changes |
| Network (polling) | High | Push notifications instead of polling |
| CPU (background) | Medium-high | Background task time limits |
| Screen rendering | Medium | Avoid unnecessary re-renders |
| Bluetooth scanning | Medium | Scan only when user initiates |
| Animations | Low-medium | Use hardware-accelerated animations |
Network Optimization
| Technique | What It Does | Savings |
|---|
| Response caching | Cache API responses locally | 50-80% fewer requests |
| Image CDN | Serve right-sized images | 60-80% image data savings |
| Request batching | Combine multiple API calls | Fewer connections |
| Delta sync | Send only changes since last sync | 90%+ data savings for sync |
| Compression | gzip/brotli responses | 60-80% response size reduction |
| Offline-first | Work without network, sync later | 100% savings when offline |
| Tool | Platform | Best For |
|---|
| Xcode Instruments | iOS | CPU, memory, energy, network profiling |
| Android Studio Profiler | Android | CPU, memory, network, energy |
| Charles Proxy | Both | Network traffic inspection |
| Firebase Performance | Both | Real-user performance monitoring |
| Flipper | Both | Debug tool with plugins |
| LeakCanary | Android | Automatic memory leak detection |
Anti-Patterns
| Anti-Pattern | Problem | Fix |
|---|
| Loading full-res images | Memory spikes, OOM crashes | Resize to display dimensions |
| Polling for updates | Battery drain, bandwidth waste | Push notifications, WebSocket |
| Synchronous network on main thread | UI freezes | Async networking, loading states |
| No image caching | Re-downloads same images | Disk + memory cache (Kingfisher, Coil) |
| Unbounded lists | Memory grows with data | Recycler views, lazy lists |
| No startup profiling | Slow cold start unnoticed | Measure and track app startup time |
Checklist
:::note[Source]
This guide is derived from operational intelligence at Garnet Grid Consulting. For mobile engineering consulting, visit garnetgrid.com.
:::
Jakub Dimitri Rezayev
Founder & Chief Architect • Garnet Grid Consulting
Jakub holds an M.S. in Customer Intelligence & Analytics and a B.S. in Finance & Computer Science from Pace University. With deep expertise spanning D365 F&O, Azure, Power BI, and AI/ML systems, he architects enterprise solutions that bridge legacy systems and modern technology — and has led multi-million dollar ERP implementations for Fortune 500 supply chains.
View Full Profile →