Skip to content

Commit a0949db

Browse files
authored
Add startup benchmark (#492)
1 parent 31d44d0 commit a0949db

File tree

9 files changed

+92
-0
lines changed

9 files changed

+92
-0
lines changed

android/app/build.gradle.kts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,11 @@ android {
5353
applicationIdSuffix = ".fast"
5454
signingConfig = signingConfigs.getByName("debug")
5555
}
56+
create("benchmark") {
57+
initWith(buildTypes.getByName("release"))
58+
signingConfig = signingConfigs.getByName("debug")
59+
matchingFallbacks += listOf("release")
60+
}
5661
release {
5762
isDebuggable = false
5863
isMinifyEnabled = true

android/app/src/main/AndroidManifest.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
android:theme="@style/Theme.HackerNews"
1717
tools:targetApi="31">
1818

19+
<profileable android:shell="true" />
20+
1921
<!-- This demonstrates manual initialization of Reaper.
2022
See https://docs.emergetools.com/docs/reaper-setup-android#disable-automatic-initialization -->
2123
<provider

android/benchmark/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/build

android/benchmark/build.gradle.kts

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
plugins {
2+
alias(libs.plugins.android.test)
3+
alias(libs.plugins.kotlin.android)
4+
}
5+
6+
android {
7+
namespace = "com.emergetools.hackernews.benchmark"
8+
compileSdk = 35
9+
10+
defaultConfig {
11+
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
12+
minSdk = 30
13+
targetSdk = 35
14+
}
15+
16+
buildTypes {
17+
// This benchmark buildType is used for benchmarking, and should function like your
18+
// release build (for example, with minification on). It"s signed with a debug key
19+
// for easy local/CI testing.
20+
create("benchmark") {
21+
isDebuggable = true
22+
signingConfig = getByName("debug").signingConfig
23+
matchingFallbacks += listOf("release")
24+
}
25+
}
26+
27+
compileOptions {
28+
sourceCompatibility = JavaVersion.VERSION_17
29+
targetCompatibility = JavaVersion.VERSION_17
30+
}
31+
kotlinOptions {
32+
jvmTarget = JavaVersion.VERSION_17.toString()
33+
}
34+
35+
targetProjectPath = ":app"
36+
experimentalProperties["android.experimental.self-instrumenting"] = true
37+
}
38+
39+
dependencies {
40+
implementation(libs.androidx.junit)
41+
implementation(libs.androidx.espresso.core)
42+
implementation(libs.androidx.uiautomator)
43+
implementation(libs.androidx.benchmark.macro.junit4)
44+
}
45+
46+
androidComponents {
47+
beforeVariants(selector().all()) {
48+
it.enable = it.buildType == "benchmark"
49+
}
50+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
<manifest />
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package com.emergetools.hackernews.benchmark
2+
3+
import androidx.benchmark.macro.StartupMode
4+
import androidx.benchmark.macro.StartupTimingMetric
5+
import androidx.benchmark.macro.junit4.MacrobenchmarkRule
6+
import androidx.test.ext.junit.runners.AndroidJUnit4
7+
import org.junit.Rule
8+
import org.junit.Test
9+
import org.junit.runner.RunWith
10+
11+
@RunWith(AndroidJUnit4::class)
12+
class StartupBenchmark {
13+
@get:Rule
14+
val benchmarkRule = MacrobenchmarkRule()
15+
16+
@Test
17+
fun startup() = benchmarkRule.measureRepeated(
18+
packageName = "com.emergetools.hackernews",
19+
metrics = listOf(StartupTimingMetric()),
20+
iterations = 5,
21+
startupMode = StartupMode.COLD
22+
) {
23+
pressHome()
24+
startActivityAndWait()
25+
}
26+
}

android/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,5 @@ plugins {
88
alias(libs.plugins.roborazzi) apply false
99
alias(libs.plugins.androidx.room) apply false
1010
alias(libs.plugins.sentry) apply false
11+
alias(libs.plugins.android.test) apply false
1112
}

android/gradle/libs.versions.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ jsoup = "1.20.1"
2929
extendedspans = "1.4.0"
3030
composeBom = "2025.06.00"
3131
uiTestJunit4Android = "1.8.3"
32+
uiautomator = "2.2.0"
33+
benchmarkMacroJunit4 = "1.2.0-beta01"
3234

3335
[libraries]
3436
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
@@ -74,6 +76,8 @@ roborazzi-rule = { group = "io.github.takahirom.roborazzi", name = "roborazzi-ju
7476
androidx-junit = { group = "androidx.test.ext", name = "junit", version.ref = "junitVersion" }
7577
androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "espressoCore" }
7678
androidx-ui-test-junit4-android = { group = "androidx.compose.ui", name = "ui-test-junit4-android", version.ref = "uiTestJunit4Android" }
79+
androidx-uiautomator = { group = "androidx.test.uiautomator", name = "uiautomator", version.ref = "uiautomator" }
80+
androidx-benchmark-macro-junit4 = { group = "androidx.benchmark", name = "benchmark-macro-junit4", version.ref = "benchmarkMacroJunit4" }
7781

7882
[plugins]
7983
android-application = { id = "com.android.application", version.ref = "agp" }
@@ -85,4 +89,5 @@ emerge = { id = "com.emergetools.android", version.ref = "emergePlugin" }
8589
sentry = { id = "io.sentry.android.gradle", version.ref = "sentry" }
8690
roborazzi = { id = "io.github.takahirom.roborazzi", version.ref = "roborazzi" }
8791
androidx-room = { id = "androidx.room", version.ref = "room" }
92+
android-test = { id = "com.android.test", version.ref = "agp" }
8893

android/settings.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,3 +49,4 @@ dependencyResolutionManagement {
4949

5050
rootProject.name = "hacker-news"
5151
include(":app")
52+
include(":benchmark")

0 commit comments

Comments
 (0)