Custom Flow Performance Analysis (Android)

This guide assumes you have already added and configured the Emerge Gradle plugin to your Android project and that you are using Android Studio or IntelliJ.

General concepts

Emerge's performance analysis focuses on catching performance differences between app builds. To do so, Emerge controls many sources of noise and variance on the real, physical device we test on to ensure any performance difference between the two comparison builds stems from the app builds alone.

UI testing

Emerge custom flow performance analysis relies on UIAutomator UI tests executing from a separate, standalone test APK against the target application. These tests must run in a separate process to ensure they are not directly affecting the performance of the target application.

Currently, custom flow performance analysis is only supported for AABs. Should your team need to test against APK(s), contact us through your dedicated Slack channel or email us.

Emerge's Gradle plugin takes care of the heavy lifting of setting up and managing this separate test APK for you. Follow the guide below to get up and running in ~10 minutes.

Create a performance testing subproject

First let's set the performance subproject path in the Emerge Gradle plugin configuration. This is where you can choose its name. Here we use performance as an example:

emerge {

    appProjectPath.set(":app") // The primary application module
    performanceProjectPath.set(":performance") // Does not need to exist, we'll create it soon!
}
emerge {
    // …
  
    performanceProjectPath = ':performance'
}

Next we'll generate the subproject and choose its package name:

./gradlew emergeGeneratePerformanceProject --package com.myapp.performance

This creates the subproject with an example performance test and adds it to settings.gradle(.kts):

674

📘

"Sync Project with Gradle Files" for your IDE to recognize the new subproject.

Write your first custom performance test

Open the newly generated ExamplePerformanceTest file. The Emerge SDK provides method annotations that work similarly to the JUnit annotations you may be used to:

  • @EmergeTest defines performance test methods. Each test method is run multiple times on an isolated device in order to detect significant performance changes. Typically this is where you would launch your app or perform an operation whose performance is critical.
  • The @EmergeSetup method is executed once before each test iteration. It is optional and is typically used to navigate to the screen where the performance testing should start. Only one setup method per class is allowed.
  • The @EmergeInit method is executed just once after the app is installed. It is optional and is typically used to log into the app, if needed. Only one init method per class is allowed.
3896

Similar to startup testing, Emerge will record disk state from base, as well as network traffic from base and head and replay across future iterations to ensure consistency.

🚧

Use of the Espresso testing framework is strongly discouraged as it can significantly degrade performance during tests. Please use UI Automator or UI Automator-based libraries like Relax instead.

Edit the ExamplePerformanceTest file to perform an operation that needs to be and remain performant. You are free to rename the class or create multiple test class.

📘

Each test runs on a different device so they cannot impact each other.

Verify performance tests locally

Emerge goes through great lengths to make performance tests reliable, like using one real device for each test, running every test dozens of times, etc. As such it is not possible to run a true performance test on your local machine. However it is possible to run your performance tests locally to ensure that they are set up correctly and can complete successfully:

./gradlew emergeLocalReleaseTest

At the end of the Gradle output you will find the verification results:

696

If there are any errors or warnings please address them.

Run performance tests on Emerge's cloud testing suite

This step requires getting in touch with our team to get set up!

Performance testing specific spans

By default, Emerge will measure the performance of your overall UI test's duration. If specific measurements are desired, Emerge's performance testing can measure the duration of specific spans from your app, leveraging Android.Trace|AndroidX.Trace functionality to mark the start and end of specific spans.

Specifying spans requires adding tracing code to the app you're measuring the performance of, using stock Android|AndroidX functionality.

1. Wrap the code you wish to measure in a Trace call:

From your app's source code, you'll need to mark the start and end of any trace using Android.Trace or AndroidX.Trace calls.

Emerge expects exactly one start/end for any specified span.

import androidx.tracing.trace

class MainActivity {

  override fun onCreate(savedInstanceState: Bundle?) {
    trace("main_activity_init") {
      initMyActivity()
    }  
  }
  
  fun initMyActivity() {
    // Performance sensitive code we want to measure
  }
}

2. Specify the span name(s) to Emerge to record.

Emerge needs a way to find your desired span, which can be provided as part of the span parameter to the @EmergeTest annotation.

class MainActivityInitTest {

  @EmergeTest(spans = ["main_activity_init"])
  fun test {
    // Example launching with Emerge's Relax library: https://github.com/EmergeTools/relax
    Relax("com.example.myapp") {
      pressHome()
      launch()
    }
  }
}

That's it! Emerge will automatically measure any specified spans measured from your UI test.