Level Up Your Android App’s Performance: A Guide to Micro benchmarking, Baseline Profiles, and Startup Profiling

Sandeep Kella
3 min readMay 7, 2024

--

In today’s competitive mobile landscape, a smooth and responsive user experience is paramount. Laggy apps lead to frustrated users and ultimately, lost business. This guide equips you with the tools to identify and address performance bottlenecks in your Android app using macrobenchmarking, baseline profiles, and startup profiling.

Understanding the Performance Powerhouse Trio

  • Macrobenchmarking: This technique measures performance for real-world user interactions like app startup, scrolling, and screen transitions. It helps pinpoint areas causing lag or jank (perceived unsmoothness). By identifying these bottlenecks, you can prioritize optimization efforts where they’ll have the biggest impact on user experience.
  • Baseline Profiles: These profiles act as a roadmap for the Android Runtime (ART) to optimize frequently used code paths. By pre-compiling this code, ART delivers snappier performance from the very first launch. This can significantly reduce startup times and improve the responsiveness of core user interactions.
  • Startup Profiling: As the name suggests, this focuses on measuring and optimizing the time it takes for your app to launch. Faster startup times lead to a more engaging user experience, especially for users on low-end devices or with slower network connections. Every second saved during startup translates to a more positive first impression.

Getting Started with Performance Profiling

Android Studio provides built-in tools to streamline the profiling process:

Create a Macrobenchmark Module: Right-click your project and choose “New” -> “Module” -> “Benchmark” (MacroBenchmark). This module houses your benchmark tests.

Craft Baseline Profiles:

  • Add the androidx.benchmark:benchmark-junit4 library to your benchmark module's build.gradle file.
  • Within the macrobenchmark module, create a class extending androidx.benchmark.macro.junit4.BaselineProfileRule.
  • Override the @Test annotated generateBaselineProfile method to simulate user interactions and capture the baseline profile. Here's an example:
@Rule
public final BaselineProfileRule baselineProfileRule = new BaselineProfileRule();

@Test
public void generateBaselineProfile() throws Exception {
// Simulate launching the app
ActivityLauncher<MyLauncherActivity> launcher = ActivityLauncher.ActivityContextLaunchConfiguration(MyLauncherActivity.class).launch(InstrumentationRegistry.getInstrumentation().getTargetContext());

// Simulate user actions on the main screen (replace with your specific actions)
onView(withId(R.id.button1)).perform(click());
onView(withId(R.id.listView)).perform(scrollToPosition(20));

// Capture the baseline profile
baselineProfileRule.generateBaselineProfile("profile_name");
}

Build Startup Benchmarks:

  • Similar to baseline profiles, create a class extending androidx.benchmark.macro.junit4.MacrobenchmarkRule.
  • Implement the @Test annotated startup or startup(CompilationMode mode) methods to simulate app launch and measure startup time. Here's an example:
@Rule
public final MacrobenchmarkRule macrobenchmarkRule = new MacrobenchmarkRule();

@Test
public void measureStartupTime() throws Exception {
long startTime = System.currentTimeMillis();
macrobenchmarkRule.launchActivity(MyLauncherActivity.class);
long endTime = System.currentTimeMillis();

// Calculate and log startup time
long startupTime = endTime - startTime;
Log.d("StartupTime", "Startup time: " + startupTime + " ms");
}

Benefits and Beyond

By incorporating these techniques, you can expect significant performance improvements:

  • Faster App Startup: Baseline profiles pre-compile frequently used code, leading to smoother launches. This can significantly reduce user wait times and improve first impressions.
  • Reduced Interaction Jank: Optimized code paths through baseline profiles ensure a more responsive user experience throughout the app. Users will experience smoother scrolling, animations, and transitions.
  • Improved Business Metrics: Faster, smoother apps translate to better user engagement, potentially leading to higher ratings, conversion rates, and user retention.

Performance Impact: Measure What Matters

When optimizing performance, it’s crucial to focus on metrics that directly impact user experience. Here are some key areas to consider:

  • Startup Time: Every second shaved off app launch time can significantly improve user perception.
  • Frame Rate: Aim for a consistent 60 frames per second (FPS) for a smooth and fluid experience.
  • Memory Usage: Excessive memory usage can lead to crashes and slowdowns.
  • Battery Drain: An energy-efficient app

--

--

Sandeep Kella

Android developer @PhonePe, writes about Android development and productivity.