diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-15 03:35:49 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-15 03:35:49 +0000 |
commit | d8bbc7858622b6d9c278469aab701ca0b609cddf (patch) | |
tree | eff41dc61d9f714852212739e6b3738b82a2af87 /mobile/android/fenix/benchmark | |
parent | Releasing progress-linux version 125.0.3-1~progress7.99u1. (diff) | |
download | firefox-d8bbc7858622b6d9c278469aab701ca0b609cddf.tar.xz firefox-d8bbc7858622b6d9c278469aab701ca0b609cddf.zip |
Merging upstream version 126.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'mobile/android/fenix/benchmark')
7 files changed, 306 insertions, 0 deletions
diff --git a/mobile/android/fenix/benchmark/build.gradle b/mobile/android/fenix/benchmark/build.gradle new file mode 100644 index 0000000000..8f13686ff4 --- /dev/null +++ b/mobile/android/fenix/benchmark/build.gradle @@ -0,0 +1,75 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +import com.android.build.api.dsl.ManagedVirtualDevice + +plugins { + id 'com.android.test' + id 'org.jetbrains.kotlin.android' +} + +android { + namespace 'org.mozilla.fenix.benchmark' + compileSdk config.compileSdkVersion + + defaultConfig { + minSdk 23 + targetSdk config.targetSdkVersion + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" + } + + buildTypes { + // This benchmark buildType is used for benchmarking, and should function like your + // release build (for example, with minification on). It's signed with a debug key + // for easy local testing. + benchmark { + debuggable = true + signingConfig signingConfigs.debug + matchingFallbacks = ["release"] + } + } + + targetProjectPath = ":app" + experimentalProperties["android.experimental.self-instrumenting"] = true + + testOptions { + managedDevices { + devices { + pixel6Api34(ManagedVirtualDevice) { + device = "Pixel 6" + apiLevel = 34 + systemImageSource = "google" + } + } + } + } +} + +/** + * This fixes the dependency resolution issue with Glean Native. The glean gradle plugin does this + * and that's applied to the app module. Since there are no other uses of the glean plugin in the + * benchmark module, we do this manually here. + */ +configurations.configureEach { + resolutionStrategy.capabilitiesResolution.withCapability("org.mozilla.telemetry:glean-native") { + def toBeSelected = candidates.find { it.id instanceof ModuleComponentIdentifier && it.id.module.contains('geckoview') } + if (toBeSelected != null) { + select(toBeSelected) + } + because 'use GeckoView Glean instead of standalone Glean' + } +} + +dependencies { + implementation ComponentsDependencies.androidx_test_junit + implementation ComponentsDependencies.androidx_espresso_core + implementation ComponentsDependencies.androidx_test_uiautomator + implementation FenixDependencies.androidx_benchmark_macro_junit4 +} + +androidComponents { + beforeVariants(selector().all()) { + enabled = buildType == "benchmark" + } +} diff --git a/mobile/android/fenix/benchmark/src/main/AndroidManifest.xml b/mobile/android/fenix/benchmark/src/main/AndroidManifest.xml new file mode 100644 index 0000000000..251d1c7b21 --- /dev/null +++ b/mobile/android/fenix/benchmark/src/main/AndroidManifest.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<manifest xmlns:android="http://schemas.android.com/apk/res/android"> + + <queries> + <package android:name="org.mozilla.fenix" /> + </queries> +</manifest> diff --git a/mobile/android/fenix/benchmark/src/main/java/org/mozilla/fenix/benchmark/BaselineProfilesStartupBenchmark.kt b/mobile/android/fenix/benchmark/src/main/java/org/mozilla/fenix/benchmark/BaselineProfilesStartupBenchmark.kt new file mode 100644 index 0000000000..ccf228584c --- /dev/null +++ b/mobile/android/fenix/benchmark/src/main/java/org/mozilla/fenix/benchmark/BaselineProfilesStartupBenchmark.kt @@ -0,0 +1,70 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.fenix.benchmark + +import android.os.Build +import androidx.annotation.RequiresApi +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 +import androidx.test.ext.junit.runners.AndroidJUnit4 +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.mozilla.fenix.benchmark.utils.measureRepeatedDefault + +/** + * This test class benchmarks the speed of app startup. Run this benchmark to verify how effective + * a Baseline Profile is. It does this by comparing [CompilationMode.None], which represents the + * app with no Baseline Profiles optimizations, and [CompilationMode.Partial], which uses Baseline Profiles. + * + * Before running make sure `autosignReleaseWithDebugKey=true` is present in local.properties. + * + * Run this benchmark to see startup measurements and captured system traces for verifying + * the effectiveness of your Baseline Profiles. You can run it directly from Android + * Studio as an instrumentation test that logs the benchmark metrics with links to the Perfetto traces, + * + * or using the gradle command: + * + * ``` + * ./gradlew :benchmark:connectedBenchmarkAndroidTest -P android.testInstrumentationRunnerArguments.class=org.mozilla.fenix.benchmark.BaselineProfilesStartupBenchmark -P benchmarkTest + * ``` + * + * The metric results will be in `benchmark/build/outputs/connected_android_test_additional_output` folder. + * + * Run the benchmarks on a physical device, not an emulator because the emulator doesn't represent + * real world performance and shares system resources with its host. + * + * For more information, see the [Macrobenchmark documentation](https://d.android.com/macrobenchmark#create-macrobenchmark) + * and the [instrumentation arguments documentation](https://d.android.com/topic/performance/benchmarking/macrobenchmark-instrumentation-args). + **/ +@RunWith(AndroidJUnit4::class) +@RequiresApi(Build.VERSION_CODES.N) +class BaselineProfilesStartupBenchmark { + + @get:Rule + val benchmarkRule = MacrobenchmarkRule() + + @Test + fun startupNone() = startupBenchmark(CompilationMode.None()) + + @Test + fun startupPartialWithBaselineProfiles() = + startupBenchmark(CompilationMode.Partial(baselineProfileMode = BaselineProfileMode.Require)) + + private fun startupBenchmark(compilationMode: CompilationMode) = + benchmarkRule.measureRepeatedDefault( + metrics = listOf(StartupTimingMetric()), + startupMode = StartupMode.COLD, + compilationMode = compilationMode, + setupBlock = { + pressHome() + }, + ) { + startActivityAndWait() + } +} diff --git a/mobile/android/fenix/benchmark/src/main/java/org/mozilla/fenix/benchmark/StartupBenchmark.kt b/mobile/android/fenix/benchmark/src/main/java/org/mozilla/fenix/benchmark/StartupBenchmark.kt new file mode 100644 index 0000000000..014df73e3a --- /dev/null +++ b/mobile/android/fenix/benchmark/src/main/java/org/mozilla/fenix/benchmark/StartupBenchmark.kt @@ -0,0 +1,49 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.fenix.benchmark + +import androidx.benchmark.macro.StartupMode +import androidx.benchmark.macro.StartupTimingMetric +import androidx.benchmark.macro.junit4.MacrobenchmarkRule +import androidx.test.ext.junit.runners.AndroidJUnit4 +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.mozilla.fenix.benchmark.utils.measureRepeatedDefault + +/** + * This is a startup benchmark. + * It navigates to the device's home screen, and launches the default activity. + * + * Before running this benchmark, + * switch your app's active build variant in the Studio (affects Studio runs only) + * + * Run this benchmark from Studio to see startup measurements, and captured system traces + * for investigating your app's performance. + */ +@RunWith(AndroidJUnit4::class) +class StartupBenchmark { + @get:Rule + val benchmarkRule = MacrobenchmarkRule() + + @Test + fun startupCold() = startupBenchmark(StartupMode.COLD) + + @Test + fun startupWarm() = startupBenchmark(StartupMode.WARM) + + @Test + fun startupHot() = startupBenchmark(StartupMode.HOT) + + private fun startupBenchmark(startupMode: StartupMode) = benchmarkRule.measureRepeatedDefault( + metrics = listOf(StartupTimingMetric()), + startupMode = startupMode, + setupBlock = { + pressHome() + } + ) { + startActivityAndWait() + } +} diff --git a/mobile/android/fenix/benchmark/src/main/java/org/mozilla/fenix/benchmark/baselineprofile/StartupOnlyBaselineProfileGenerator.kt b/mobile/android/fenix/benchmark/src/main/java/org/mozilla/fenix/benchmark/baselineprofile/StartupOnlyBaselineProfileGenerator.kt new file mode 100644 index 0000000000..f8e26847b5 --- /dev/null +++ b/mobile/android/fenix/benchmark/src/main/java/org/mozilla/fenix/benchmark/baselineprofile/StartupOnlyBaselineProfileGenerator.kt @@ -0,0 +1,60 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.fenix.benchmark.baselineprofile + +import android.os.Build +import androidx.annotation.RequiresApi +import androidx.benchmark.macro.junit4.BaselineProfileRule +import androidx.test.ext.junit.runners.AndroidJUnit4 +import org.junit.Rule +import org.junit.Test +import org.junit.runner.RunWith +import org.mozilla.fenix.benchmark.utils.TARGET_PACKAGE + +/** + * This test class generates a basic startup baseline profile for the target package. + * + * Refer to the [baseline profile documentation](https://d.android.com/topic/performance/baselineprofiles) + * for more information. + * + * Make sure `autosignReleaseWithDebugKey=true` is present in local.properties. + * + * Generate the baseline profile using this gradle task: + * ``` + * ./gradlew :benchmark:pixel6Api34BenchmarkAndroidTest -P android.testInstrumentationRunnerArguments.class=org.mozilla.fenix.benchmark.baselineprofile.StartupOnlyBaselineProfileGenerator -P benchmarkTest -P disableOptimization + * ``` + * + * Check [documentation](https://d.android.com/topic/performance/benchmarking/macrobenchmark-instrumentation-args) + * for more information about available instrumentation arguments. + * + * As the experiment is only for nightly, run + * ``` + * ./gradlew copyBaselineProfile + * ``` + * This will copy the baseline profiles to the nightly folder. These are the profiles that will be compiled with the nightly build. + * + * Then, copy the profiles to app/src/benchmark/baselineProfiles to verify the improvements by running + * the [org.mozilla.fenix.benchmark.BaselineProfilesStartupBenchmark] benchmark. + * Notice that when we run the benchmark, we run the benchmark variant and not the nightly so copying the profiles here is important. + * These shouldn't be pushed to version control. + * + * When using this class to generate a baseline profile, only API 33+ or rooted API 28+ are supported. + **/ +@RequiresApi(Build.VERSION_CODES.P) +@RunWith(AndroidJUnit4::class) +class StartupOnlyBaselineProfileGenerator { + + @get:Rule + val rule = BaselineProfileRule() + + @Test + fun generateBaselineProfile() { + rule.collect( + packageName = TARGET_PACKAGE, + ) { + startActivityAndWait() + } + } +} diff --git a/mobile/android/fenix/benchmark/src/main/java/org/mozilla/fenix/benchmark/utils/Constants.kt b/mobile/android/fenix/benchmark/src/main/java/org/mozilla/fenix/benchmark/utils/Constants.kt new file mode 100644 index 0000000000..14fe426118 --- /dev/null +++ b/mobile/android/fenix/benchmark/src/main/java/org/mozilla/fenix/benchmark/utils/Constants.kt @@ -0,0 +1,8 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.fenix.benchmark.utils + +const val TARGET_PACKAGE = "org.mozilla.fenix" +const val DEFAULT_ITERATIONS = 5 diff --git a/mobile/android/fenix/benchmark/src/main/java/org/mozilla/fenix/benchmark/utils/MacroBenchmarkRule.kt b/mobile/android/fenix/benchmark/src/main/java/org/mozilla/fenix/benchmark/utils/MacroBenchmarkRule.kt new file mode 100644 index 0000000000..d3fbd499cf --- /dev/null +++ b/mobile/android/fenix/benchmark/src/main/java/org/mozilla/fenix/benchmark/utils/MacroBenchmarkRule.kt @@ -0,0 +1,37 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.fenix.benchmark.utils + +import androidx.annotation.IntRange +import androidx.benchmark.macro.CompilationMode +import androidx.benchmark.macro.MacrobenchmarkScope +import androidx.benchmark.macro.Metric +import androidx.benchmark.macro.StartupMode +import androidx.benchmark.macro.junit4.MacrobenchmarkRule + +/** + * Extension function that calls [MacrobenchmarkRule.measureRepeated] with + * defaults parameters set for [packageName] and [iterations]. + */ +fun MacrobenchmarkRule.measureRepeatedDefault( + packageName: String = TARGET_PACKAGE, + metrics: List<Metric>, + compilationMode: CompilationMode = CompilationMode.DEFAULT, + startupMode: StartupMode? = null, + @IntRange(from = 1) + iterations: Int = DEFAULT_ITERATIONS, + setupBlock: MacrobenchmarkScope.() -> Unit = {}, + measureBlock: MacrobenchmarkScope.() -> Unit, +) { + measureRepeated( + packageName = packageName, + metrics = metrics, + compilationMode = compilationMode, + startupMode = startupMode, + iterations = iterations, + setupBlock = setupBlock, + measureBlock = measureBlock, + ) +} |