0Pricing
Android Academy · Lesson

Startup and Baseline Profiles

Faster cold starts.

Startup and Baseline Profiles is a free Android Academy lesson on CoddyKit — lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Android Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

First Impressions: App Startup

Startup time is the first thing every user experiences. Google Play even surfaces slow startup as a quality issue. A fast cold start makes an app feel premium; a slow one makes users bounce.

In this lesson you will learn the three startup types, what makes startup slow, and the modern tools — App Startup and Baseline Profiles — that make cold starts dramatically faster.

Cold, Warm, and Hot Start

Android defines three startup scenarios, from slowest to fastest:

  • Cold start: the process does not exist. Android creates it, runs Application, then your first screen. The slowest and most important to optimize.
  • Warm start: the process is alive but the Activity must be recreated.
  • Hot start: the Activity is still in memory; just bring it to front. Nearly instant.

Optimization effort focuses on the cold start, because that is what new and returning users hit most.

Measuring Startup Time

You cannot improve what you do not measure. Two easy ways:

  • Logcat: the system logs a Displayed line with time-to-first-frame.
  • Macrobenchmark: StartupTimingMetric gives stable, repeatable cold-start numbers.

Run the adb command below and watch for the Displayed line.

# Cold-start the app and log time to first frame
adb shell am start -W -S com.example.app/.MainActivity

# Output includes:
#   TotalTime: 412   <- ms to first frame
# Or filter logcat:
adb logcat | grep "Displayed com.example.app"

Keep Application.onCreate Light

Everything in Application.onCreate() runs on the main thread before your first frame. Heavy initialization here directly delays startup.

The bad version below initializes several libraries eagerly. Defer or background anything not needed for the first screen.

// SLOW: blocks the first frame with eager init
class MyApp : Application() {
    override fun onCreate() {
        super.onCreate()
        Analytics.init(this)        // network, disk
        ImageLoader.preload(this)   // heavy
        Database.warmUp(this)       // disk I/O
    }
}
// Each of these adds milliseconds before the user sees anything.

The Jetpack App Startup Library

The App Startup library replaces multiple library content providers (each costing time) with a single shared one, and lets you express initialization order and dependencies cleanly.

You implement an Initializer per component; App Startup runs them once, in dependency order.

class AnalyticsInitializer : Initializer<Analytics> {
    override fun create(context: Context): Analytics {
        return Analytics.init(context.applicationContext)
    }
    // Runs after Logger is ready
    override fun dependencies() = listOf(LoggerInitializer::class.java)
}
// Registered via a single merged provider in the manifest,
// avoiding one ContentProvider per library.

Lazy and Background Initialization

Better than ordering eager work is doing less of it at startup. Two tactics:

  • Lazy: build heavy objects on first use with Kotlin's by lazy.
  • Background: move non-UI initialization off the main thread.

Now the first frame is not blocked by work the user does not yet need.

class MyApp : Application() {
    // Built only when first accessed, not during onCreate
    val imageLoader by lazy { ImageLoader.build(this) }

    override fun onCreate() {
        super.onCreate()
        // Push non-critical setup off the main thread
        CoroutineScope(Dispatchers.Default).launch {
            Analytics.init(applicationContext)
        }
    }
}

AOT vs JIT: Why the First Run Is Slow

By default, Android runs your app's bytecode with a mix of interpretation and Just-In-Time (JIT) compilation. The first time hot code runs, it is interpreted (slow); only later does the runtime compile it to native code.

This is exactly why cold start and the first scroll feel slower. Baseline Profiles fix this by telling the device to compile the important code Ahead-Of-Time (AOT) at install.

What a Baseline Profile Is

A Baseline Profile is a list of the classes and methods exercised during your critical journeys (startup, first scroll). You ship it with the app; at install the device AOT-compiles those methods, so they run at native speed from the very first launch.

Google reports startup improvements often in the 20–40% range, with no code changes to your features — just the profile.

// build.gradle.kts
plugins { id("androidx.baselineprofile") }

dependencies {
    baselineProfile(project(":baselineprofile"))
}
// The generated profile ships as
//   assets/dexopt/baseline.prof
// and is applied automatically at install.

Generating a Baseline Profile

You generate the profile by writing a small test that drives your critical path on a device; the tooling records which methods ran and writes the profile file. You then commit it and rebuild.

Here is a typical generator that captures startup and a scroll.

@RunWith(AndroidJUnit4::class)
class BaselineProfileGenerator {
    @get:Rule val rule = BaselineProfileRule()

    @Test
    fun generate() = rule.collect(packageName = "com.example.app") {
        pressHome()
        startActivityAndWait()
        // exercise the critical journey
        device.findObject(By.res("feed")).fling(Direction.DOWN)
    }
}
// Run the generateBaselineProfile Gradle task to produce the file.

Verifying the Win

Always confirm the improvement with a benchmark, comparing startup with and without the profile applied (CompilationMode.None vs Partial with the profile).

If you do not measure, you cannot prove the profile helped — and an outdated profile can even hurt. Regenerate it whenever your hot paths change significantly.

@Test
fun startupWithProfile() = rule.measureRepeated(
    packageName = "com.example.app",
    metrics = listOf(StartupTimingMetric()),
    iterations = 10,
    startupMode = StartupMode.COLD,
    compilationMode = CompilationMode.Partial() // uses the baseline profile
) {
    pressHome()
    startActivityAndWait()
}

A Startup Optimization Plan

Put it together into a repeatable plan:

  • Measure cold start with Macrobenchmark and adb am start -W.
  • Trim Application.onCreate: defer with by lazy, move work off the main thread.
  • Use App Startup to merge content providers and order init.
  • Ship a Baseline Profile for AOT compilation of the critical path.
  • Verify with a benchmark and keep the profile fresh.

The result: a snappy first frame that users notice.

Quick Check

You ship a Baseline Profile with your app. What does it primarily do to improve startup?

Recap: Fast From the First Frame

You learned to optimize startup, the most visible performance metric:

  • Optimize the cold start; measure with Macrobenchmark and adb am start -W.
  • Keep Application.onCreate light: lazy init and background non-UI work.
  • Use the App Startup library to merge providers and order initializers.
  • Ship a Baseline Profile so hot code is AOT-compiled at install for native speed on first run.
  • Always verify the win with a benchmark and keep the profile current.

That completes Performance Optimization & Profiling: you can now measure, tame recomposition, fix leaks, and start fast.

Frequently asked questions

Is the “Startup and Baseline Profiles” lesson free?

Yes — the full text of “Startup and Baseline Profiles” is free to read here on the web, and the Android Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Android Academy course, upgrade to CoddyKit PRO.

What will I learn in “Startup and Baseline Profiles”?

Faster cold starts. You practise Android Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start Android Academy?

No prior experience is required. Android Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Startup and Baseline Profiles” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this Android Academy lesson?

Yes. Every Android Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Measuring Performance
  2. Taming Recomposition
  3. Memory Leaks and Fixes
  4. Startup and Baseline Profiles
← Back to Android Academy