App Startup Optimization
📖 Concept
App startup time is one of the most critical performance metrics. Google recommends cold start < 500ms. At the senior level, you need to understand the startup phases, profiling tools, and optimization techniques.
Startup types:
- Cold start: Process not running. Full initialization: Zygote fork → Application.onCreate() → Activity.onCreate() → first frame. Slowest.
- Warm start: Process exists but Activity is recreated. Skips process creation.
- Hot start: Activity is in memory, just brought to foreground. Fastest.
Cold start phases:
1. Process creation (Zygote fork) ~50-100ms (OS, can't optimize)
2. Application.onCreate() ← YOUR optimization target
3. Activity.onCreate() ← YOUR optimization target
4. Layout inflation & measure/layout ← YOUR optimization target
5. First frame rendered (TTID) ← The metric that matters
Key metrics:
- TTID (Time To Initial Display): Time until the first frame is drawn. Reported in Logcat as "Displayed" time.
- TTFD (Time To Full Display): Time until all async data is loaded and the full UI is visible.
Optimization strategies:
- Lazy initialization: Don't initialize everything in Application.onCreate(). Use the App Startup library for on-demand initialization.
- Background initialization: Move non-critical init to background threads.
- Baseline Profiles: AOT-compile critical code paths for 30-40% faster startup.
- Reduce layout complexity: Fewer nested layouts = faster inflate and measure.
- Splash screen: Use the SplashScreen API (Android 12+) to provide instant visual feedback.
💻 Code Example
1// BAD: Heavy initialization in Application ❌2class MyApplication : Application() {3 override fun onCreate() {4 super.onCreate()5 // Each of these blocks the main thread!6 Analytics.init(this) // 200ms7 CrashReporting.init(this) // 100ms8 ImageLoader.init(this) // 150ms9 Database.init(this) // 300ms10 // Total: 750ms blocked on main thread!11 }12}1314// GOOD: Lazy + background initialization ✅15class MyApplication : Application() {16 override fun onCreate() {17 super.onCreate()18 // Only critical, fast initializations on main thread19 CrashReporting.init(this) // Must be first for crash capture2021 // Everything else: lazy or background22 ProcessLifecycleOwner.get().lifecycle.addObserver(23 object : DefaultLifecycleObserver {24 override fun onCreate(owner: LifecycleOwner) {25 CoroutineScope(Dispatchers.Default).launch {26 Analytics.init(this@MyApplication)27 ImageLoader.init(this@MyApplication)28 }29 }30 }31 )32 }33}3435// App Startup Library — declarative lazy initialization36class AnalyticsInitializer : Initializer<Analytics> {37 override fun create(context: Context): Analytics {38 return Analytics.Builder(context).build()39 }40 override fun dependencies(): List<Class<out Initializer<*>>> {41 return listOf(CrashReportingInitializer::class.java)42 }43}4445// Baseline Profiles — critical for startup optimization46// baseline-prof.txt in app/src/main/47// Tells ART to AOT-compile these methods48// HSPLcom/myapp/MainActivity;->onCreate(Landroid/os/Bundle;)V49// Generated via Macrobenchmark:50@RunWith(AndroidJUnit4::class)51class BaselineProfileGenerator {52 @get:Rule53 val rule = BaselineProfileRule()5455 @Test56 fun generateBaselineProfile() {57 rule.collect(packageName = "com.myapp") {58 startActivityAndWait()59 // Navigate through critical user journeys60 device.findObject(By.text("Login")).click()61 device.waitForIdle()62 }63 }64}
🏋️ Practice Exercise
Practice:
- Profile your app's cold start time using
adb shell am start -S -W - Implement lazy initialization using the App Startup library
- Generate a Baseline Profile and measure the startup improvement
- Identify 3 things in your Application.onCreate() that can be deferred
- Explain the SplashScreen API vs a custom splash Activity
- What is the Zygote process and how does it speed up app creation?
⚠️ Common Mistakes
Initializing all SDKs synchronously in Application.onCreate() — this is the #1 cause of slow cold starts
Using a custom splash Activity instead of the SplashScreen API — adds an extra Activity creation to the startup path
Not measuring startup time properly — use Macrobenchmark, not manual timing
Ignoring Baseline Profiles — they can improve startup by 30-40% with minimal effort
💼 Interview Questions
🎤 Mock Interview
Mock interview is powered by AI for App Startup Optimization. Login to unlock this feature.