Mobile App Performance
Optimize mobile application performance for speed, responsiveness, and battery life. Covers startup time, rendering performance, memory management, network optimization, battery impact, and the patterns that make mobile apps feel instant.
Mobile performance is unforgiving. Users abandon apps that take more than 3 seconds to launch, scroll jank is immediately noticeable, and battery drain gets your app uninstalled. Unlike web performance where you optimize for Core Web Vitals, mobile performance requires optimizing for CPU-constrained devices, limited memory, variable network conditions, and battery life.
Startup Time Optimization
App Launch Phases:
1. Process creation (OS-level, unavoidable)
2. Runtime initialization
3. Application initialization
4. First frame rendered ← User sees content
Cold Start Targets:
Excellent: < 1 second
Good: 1-2 seconds
Poor: > 2 seconds
Optimization Strategies:
☐ Defer non-critical initialization
☐ Lazy-load modules not needed on first screen
☐ Cache first screen data locally
☐ Show skeleton UI immediately
☐ Reduce dependency injection graph
☐ Pre-warm data in background after launch
iOS Startup
// Measure app launch time
class AppDelegate: UIResponder, UIApplicationDelegate {
let launchStart = CFAbsoluteTimeGetCurrent()
func application(_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// CRITICAL: Only essential initialization here
configureAnalytics()
configureAuth()
// DEFER: Non-critical initialization
DispatchQueue.global().async {
self.configureFeatureFlags()
self.prefetchData()
self.initializeSDKs()
}
let launchTime = CFAbsoluteTimeGetCurrent() - launchStart
Analytics.track("app_launch", properties: ["duration_ms": launchTime * 1000])
return true
}
}
// Lazy-load view controllers
class MainTabBarController: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
// Only create the first tab immediately
let homeVC = HomeViewController()
// Other tabs lazy-loaded when tapped
let searchVC = LazyViewController { SearchViewController() }
let profileVC = LazyViewController { ProfileViewController() }
viewControllers = [homeVC, searchVC, profileVC]
}
}
Android Startup
// Baseline Profiles: Pre-compile hot paths
// baseline-prof.txt
HSPLcom/app/MainActivity;->onCreate(Landroid/os/Bundle;)V
HSPLcom/app/data/Repository;->getData()Lkotlinx/coroutines/flow/Flow;
// App Startup Library: Control initialization order
class AnalyticsInitializer : Initializer<Analytics> {
override fun create(context: Context): Analytics {
return Analytics.init(context)
}
override fun dependencies(): List<Class<out Initializer<*>>> {
return emptyList() // No dependencies, can init early
}
}
class FeatureFlagInitializer : Initializer<FeatureFlags> {
override fun create(context: Context): FeatureFlags {
return FeatureFlags.init(context) // Can be async
}
override fun dependencies(): List<Class<out Initializer<*>>> {
return listOf(AnalyticsInitializer::class.java)
}
}
Network Optimization
Strategies:
1. Cache aggressively
- Cache API responses
- Offline-first with background sync
- Image caching with disk + memory layers
2. Reduce payload size
- gzip/brotli compression
- Pagination and lazy loading
- GraphQL: request only needed fields
- Protobuf instead of JSON (30-50% smaller)
3. Minimize requests
- Batch API calls
- Prefetch predictable data
- Use push (WebSocket) instead of polling
4. Handle poor connectivity
- Retry with exponential backoff
- Show cached data with staleness indicator
- Queue mutations for later sync
Anti-Patterns
| Anti-Pattern | Consequence | Fix |
|---|---|---|
| Init everything at launch | Slow startup, poor first impression | Lazy and deferred initialization |
| Blocking main thread | UI freezes, ANRs | Offload work to background threads |
| No image caching | Repeated downloads, data waste | Disk + memory image cache (SDWebImage, Coil) |
| Polling for updates | Battery drain, data waste | Push notifications, WebSockets |
| No performance baseline | Cannot detect regressions | Benchmark tests, performance monitoring |
Mobile performance is not an optimization — it is a feature. Users cannot see your architecture, but they can feel your performance.