Skip to content
This repository has been archived by the owner on Jun 17, 2024. It is now read-only.

Commit

Permalink
Bug 1807324 - Add macrobenchmarks for startup metrics
Browse files Browse the repository at this point in the history
  • Loading branch information
rahulsainani committed Feb 23, 2023
1 parent fd1e41a commit 610c40d
Show file tree
Hide file tree
Showing 10 changed files with 176 additions and 2 deletions.
8 changes: 8 additions & 0 deletions fenix/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,11 @@ android {
"deepLinkScheme": deepLinkSchemeValue
]
}
benchmark releaseTemplate >> {
initWith buildTypes.nightly
applicationIdSuffix ".fenix"
debuggable false
}
}

buildFeatures {
Expand Down Expand Up @@ -448,6 +453,7 @@ nimbus {
fenixNightly: "nightly",
fenixBeta: "beta",
fenixRelease: "release",
fenixBenchmark: "developer",
]
// This is generated by the FML and should be checked into git.
// It will be fetched by Experimenter (the Nimbus experiment website)
Expand Down Expand Up @@ -621,6 +627,8 @@ dependencies {
implementation FenixDependencies.google_play_review
implementation FenixDependencies.google_play_review_ktx

implementation FenixDependencies.androidx_profileinstaller

androidTestImplementation FenixDependencies.uiautomator
androidTestImplementation "tools.fastlane:screengrab:2.0.0"
// This Falcon version is added to maven central now required for Screengrab
Expand Down
4 changes: 4 additions & 0 deletions fenix/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@
android:usesCleartextTraffic="true"
tools:ignore="UnusedAttribute">

<profileable
android:shell="true"
tools:targetApi="29" />

<!--
We inherited this entry (${applicationId}.App) from Fennec. We need to keep this as our
main launcher to avoid launcher icons on the home screen disappearing for all our users.
Expand Down
2 changes: 1 addition & 1 deletion fenix/app/src/main/java/org/mozilla/fenix/Config.kt
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ enum class ReleaseChannel {
object Config {
val channel = when (BuildConfig.BUILD_TYPE) {
"debug" -> ReleaseChannel.Debug
"nightly" -> ReleaseChannel.Nightly
"nightly", "benchmark" -> ReleaseChannel.Nightly
"beta" -> ReleaseChannel.Beta
"release" -> ReleaseChannel.Release
else -> {
Expand Down
69 changes: 69 additions & 0 deletions fenix/benchmark/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
plugins {
id 'com.android.test'
id 'org.jetbrains.kotlin.android'
}

android {
namespace 'org.mozilla.fenix.benchmark'
compileSdk Config.compileSdkVersion

compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}

kotlinOptions {
jvmTarget = "1.8"
}

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/CI testing.
benchmark {
debuggable = true
if (gradle.hasProperty("localProperties.autosignReleaseWithDebugKey")) {
signingConfig signingConfigs.debug
}
matchingFallbacks = ["release"]
}
}

targetProjectPath = ":app"
experimentalProperties["android.experimental.self-instrumenting"] = true
}

/**
* 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.all {
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 FenixDependencies.kotlin_stdlib
implementation FenixDependencies.androidx_junit
implementation FenixDependencies.espresso_core
implementation FenixDependencies.uiautomator
implementation FenixDependencies.androidx_benchmark_macro_junit4
}

androidComponents {
beforeVariants(selector().all()) {
enabled = buildType == "benchmark"
}
}
7 changes: 7 additions & 0 deletions fenix/benchmark/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -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>
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
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()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package org.mozilla.fenix.benchmark.utils

const val TARGET_PACKAGE = "org.mozilla.fenix"
const val DEFAULT_ITERATIONS = 5
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
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,
)
}
5 changes: 4 additions & 1 deletion fenix/buildSrc/src/main/java/FenixDependencies.kt
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,12 @@ object FenixVersions {
const val androidx_compose = "1.3.1"
const val androidx_compose_compiler = "1.3.2"
const val androidx_appcompat = "1.3.0"
const val androidx_benchmark = "1.0.0"
const val androidx_benchmark = "1.1.1"
const val androidx_biometric = "1.1.0"
const val androidx_coordinator_layout = "1.1.0"
const val androidx_constraint_layout = "2.0.4"
const val androidx_preference = "1.1.1"
const val androidx_profileinstaller = "1.2.2"
const val androidx_legacy = "1.0.0"
const val androidx_annotation = "1.5.0"
const val androidx_lifecycle = "2.5.1"
Expand Down Expand Up @@ -85,6 +86,8 @@ object FenixDependencies {
const val androidx_compose_material = "androidx.compose.material:material:${FenixVersions.androidx_compose}"
const val androidx_annotation = "androidx.annotation:annotation:${FenixVersions.androidx_annotation}"
const val androidx_benchmark_junit4 = "androidx.benchmark:benchmark-junit4:${FenixVersions.androidx_benchmark}"
const val androidx_benchmark_macro_junit4 = "androidx.benchmark:benchmark-macro-junit4:${FenixVersions.androidx_benchmark}"
const val androidx_profileinstaller = "androidx.profileinstaller:profileinstaller:${FenixVersions.androidx_profileinstaller}"
const val androidx_biometric = "androidx.biometric:biometric:${FenixVersions.androidx_biometric}"
const val androidx_fragment = "androidx.fragment:fragment-ktx:${FenixVersions.androidx_fragment}"
const val androidx_appcompat = "androidx.appcompat:appcompat:${FenixVersions.androidx_appcompat}"
Expand Down
1 change: 1 addition & 0 deletions fenix/settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ plugins {
include ':app'
include ':mozilla-detekt-rules'
include ':mozilla-lint-rules'
include ':benchmark'

// Synchronized library configuration for all modules
// This "componentsVersion" number is defined in "version.txt" and should follow
Expand Down

0 comments on commit 610c40d

Please sign in to comment.