diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 4789362..9bf47f8 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -51,7 +51,7 @@ jobs: - name: Build release variant including baseline profile generation run: ./gradlew :app:assembleRelease - -Pandroid.testInstrumentationRunnerArguments.androidx.benchmark.enabledRules=BaselineProfile + -Dorg.gradle.workers.max=1 -Pandroid.testoptions.manageddevices.emulator.gpu="swiftshader_indirect" -Pandroid.experimental.testOptions.managedDevices.emulator.showKernelLogging=true -Pandroid.experimental.androidTest.numManagedDeviceShards=1 diff --git a/baselineprofile/src/main/kotlin/com/joeloewi/jumpkking/baselineprofile/BaselineProfileGenerator.kt b/baselineprofile/src/main/kotlin/com/joeloewi/jumpkking/baselineprofile/BaselineProfileGenerator.kt new file mode 100644 index 0000000..33649ff --- /dev/null +++ b/baselineprofile/src/main/kotlin/com/joeloewi/jumpkking/baselineprofile/BaselineProfileGenerator.kt @@ -0,0 +1,67 @@ +package com.joeloewi.jumpkking.baselineprofile + +import androidx.benchmark.macro.junit4.BaselineProfileRule +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.LargeTest +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith + +/** + * This test class generates a basic startup baseline profile for the target package. + * + * We recommend you start with this but add important user flows to the profile to improve their performance. + * Refer to the [baseline profile documentation](https://d.android.com/topic/performance/baselineprofiles) + * for more information. + * + * You can run the generator with the Generate Baseline Profile run configuration, + * or directly with `generateBaselineProfile` Gradle task: + * ``` + * ./gradlew :app:generateReleaseBaselineProfile -Pandroid.testInstrumentationRunnerArguments.androidx.benchmark.enabledRules=BaselineProfile + * ``` + * The run configuration runs the Gradle task and applies filtering to run only the generators. + * + * Check [documentation](https://d.android.com/topic/performance/benchmarking/macrobenchmark-instrumentation-args) + * for more information about available instrumentation arguments. + * + * After you run the generator, you can verify the improvements running the [StartupBenchmarks] benchmark. + * + * When using this class to generate a baseline profile, only API 33+ or rooted API 26+ are supported. + **/ +@RunWith(AndroidJUnit4::class) +@LargeTest +class BaselineProfileGenerator { + + @get:Rule + val rule = BaselineProfileRule() + + @Test + fun generate() { + rule.collect( + packageName = "com.joeloewi.jumpkking", + includeInStartupProfile = true + ) { + pressHome() + startActivityAndWait() + } + + rule.collect("com.joeloewi.jumpkking") { + // This block defines the app's critical user journey. Here we are interested in + // optimizing for app startup. But you can also navigate and scroll + // through your most important UI. + + // Start default activity for your app + pressHome() + startActivityAndWait() + + // TODO Write more interactions to optimize advanced journeys of your app. + // For example: + // 1. Wait until the content is asynchronously loaded + // 2. Scroll the feed content + // 3. Navigate to detail screen + + // Check UiAutomator documentation for more information how to interact with the app. + // https://d.android.com/training/testing/other-components/ui-automator + } + } +} \ No newline at end of file diff --git a/baselineprofile/src/main/kotlin/com/joeloewi/jumpkking/baselineprofile/ExampleStartupBenchmark.kt b/baselineprofile/src/main/kotlin/com/joeloewi/jumpkking/baselineprofile/ExampleStartupBenchmark.kt index 3dd6f50..469b42c 100644 --- a/baselineprofile/src/main/kotlin/com/joeloewi/jumpkking/baselineprofile/ExampleStartupBenchmark.kt +++ b/baselineprofile/src/main/kotlin/com/joeloewi/jumpkking/baselineprofile/ExampleStartupBenchmark.kt @@ -1,5 +1,7 @@ package com.joeloewi.jumpkking.baselineprofile +import androidx.benchmark.macro.BaselineProfileMode +import androidx.benchmark.macro.CompilationMode import androidx.benchmark.macro.StartupMode import androidx.benchmark.macro.StartupTimingMetric import androidx.benchmark.macro.junit4.MacrobenchmarkRule @@ -23,16 +25,38 @@ import org.junit.runner.RunWith @RunWith(AndroidJUnit4::class) class ExampleStartupBenchmark { @get:Rule - val benchmarkRule = MacrobenchmarkRule() + val rule = MacrobenchmarkRule() @Test - fun startup() = benchmarkRule.measureRepeated( - packageName = "com.joeloewi.jumpkking", - metrics = listOf(StartupTimingMetric()), - iterations = 5, - startupMode = StartupMode.COLD - ) { - pressHome() - startActivityAndWait() + fun startupCompilationNone() = + benchmark(CompilationMode.None()) + + @Test + fun startupCompilationBaselineProfiles() = + benchmark(CompilationMode.Partial(BaselineProfileMode.Require)) + + private fun benchmark(compilationMode: CompilationMode) { + rule.measureRepeated( + packageName = "com.joeloewi.jumpkking", + metrics = listOf(StartupTimingMetric()), + compilationMode = compilationMode, + startupMode = StartupMode.COLD, + iterations = 10, + setupBlock = { + pressHome() + }, + measureBlock = { + startActivityAndWait() + + // TODO Add interactions to wait for when your app is fully drawn. + // The app is fully drawn when Activity.reportFullyDrawn is called. + // For Jetpack Compose, you can use ReportDrawn, ReportDrawnWhen and ReportDrawnAfter + // from the AndroidX Activity library. + + // Check the UiAutomator documentation for more information on how to + // interact with the app. + // https://d.android.com/training/testing/other-components/ui-automator + } + ) } } \ No newline at end of file