diff --git a/README.md b/README.md
index ba0cbab4..14c47e92 100644
--- a/README.md
+++ b/README.md
@@ -40,6 +40,27 @@ Read [this](https://github.com/sadellie/unitto/wiki/Security).
## 🤖 Custom ROM developers
Leave.
+## 🤓 Nerds
+
+
+Benchmarks and Baseline profile
+
+```
+Pixel 8 - 14
+
+StartupBenchmark_startupPrecompiledWithBaselineProfile
+timeToInitialDisplayMs min 183.5, median 219.9, max 247.3
+
+StartupBenchmark_startupWithoutPreCompilation
+timeToInitialDisplayMs min 223.6, median 328.0, max 663.8
+
+StartupBenchmark_startupWithPartialCompilationAndDisabledBaselineProfile
+timeToInitialDisplayMs min 264.8, median 308.0, max 376.1
+StartupBenchmark_startupFullyPrecompiled
+timeToInitialDisplayMs min 314.4, median 336.9, max 388.3
+```
+
+
## 🔎 Additional
Terms and Conditions: https://sadellie.github.io/unitto/terms
diff --git a/app/benchmark-rules.pro b/app/benchmark-rules.pro
new file mode 100644
index 00000000..5fa87d01
--- /dev/null
+++ b/app/benchmark-rules.pro
@@ -0,0 +1,6 @@
+# Proguard rules for the `benchmark` build type.
+#
+# Obsfuscation must be disabled for the build variant that generates Baseline Profile, otherwise
+# wrong symbols would be generated. The generated Baseline Profile will be properly applied when generated
+# without obfuscation and your app is being obfuscated.
+-dontobfuscate
diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index 430b5cda..9e97ae09 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -24,6 +24,7 @@ plugins {
id("unitto.android.application.jacoco")
id("jacoco")
id("unitto.android.hilt")
+ alias(libs.plugins.baselineprofile)
}
android {
@@ -73,8 +74,11 @@ android {
}
create("benchmark") {
initWith(buildTypes.getByName("release"))
+ matchingFallbacks.add("release")
signingConfig = signingConfigs.getByName("debug")
- matchingFallbacks += listOf("release")
+ // Only use benchmark proguard rules
+ proguardFiles("benchmark-rules.pro")
+ isMinifyEnabled = true
}
}
@@ -122,6 +126,7 @@ tasks.withType().configureEach
dependencies {
implementation(libs.androidx.core.core.ktx)
+ implementation(libs.androidx.profileinstaller.profileinstaller)
coreLibraryDesugaring(libs.com.android.tools.desugar.jdk.libs)
implementation(libs.androidx.compose.material3)
@@ -144,4 +149,12 @@ dependencies {
implementation(project(":data:userprefs"))
implementation(project(":core:ui"))
implementation(project(":core:base"))
+
+ baselineProfile(project(":benchmark"))
+}
+
+baselineProfile {
+ // Don't build on every iteration of a full assemble.
+ // Instead enable generation directly for the release build variant.
+ automaticGenerationDuringBuild = false
}
diff --git a/benchmark/build.gradle.kts b/benchmark/build.gradle.kts
index 7e257d9b..c9ea266a 100644
--- a/benchmark/build.gradle.kts
+++ b/benchmark/build.gradle.kts
@@ -38,8 +38,8 @@ android {
// for easy local/CI testing.
create("benchmark") {
isDebuggable = true
- signingConfig = getByName("debug").signingConfig
- matchingFallbacks += listOf("release")
+ signingConfig = signingConfigs.getByName("debug")
+ matchingFallbacks.add("release")
}
}
diff --git a/benchmark/src/main/java/com/sadellie/unitto/benchmark/StartupBenchmark.kt b/benchmark/src/main/java/com/sadellie/unitto/benchmark/StartupBenchmark.kt
index 6b1f7b20..a69e6fd3 100644
--- a/benchmark/src/main/java/com/sadellie/unitto/benchmark/StartupBenchmark.kt
+++ b/benchmark/src/main/java/com/sadellie/unitto/benchmark/StartupBenchmark.kt
@@ -18,6 +18,8 @@
package com.sadellie.unitto.benchmark
+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
@@ -44,13 +46,32 @@ class StartupBenchmark {
val benchmarkRule = MacrobenchmarkRule()
@Test
- fun startup() = benchmarkRule.measureRepeated(
+ fun startupWithoutPreCompilation() = startup(CompilationMode.None())
+
+ @Test
+ fun startupWithPartialCompilationAndDisabledBaselineProfile() = startup(
+ CompilationMode.Partial(baselineProfileMode = BaselineProfileMode.Disable, warmupIterations = 1),
+ )
+
+ @Test
+ fun startupPrecompiledWithBaselineProfile() =
+ startup(CompilationMode.Partial(baselineProfileMode = BaselineProfileMode.Require))
+
+ @Test
+ fun startupFullyPrecompiled() = startup(CompilationMode.Full())
+
+ private fun startup(
+ compilationMode: CompilationMode
+ ) = benchmarkRule.measureRepeated(
packageName = "com.sadellie.unitto",
metrics = listOf(StartupTimingMetric()),
- iterations = 5,
- startupMode = StartupMode.COLD
+ compilationMode = compilationMode,
+ iterations = 10,
+ startupMode = StartupMode.COLD,
+ setupBlock = {
+ pressHome()
+ }
) {
- pressHome()
startActivityAndWait()
}
}
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
index afdf530b..0f36b56a 100644
--- a/gradle/libs.versions.toml
+++ b/gradle/libs.versions.toml
@@ -16,6 +16,7 @@ androidxHiltHiltNavigationCompose = "1.1.0"
androidxMacroBenchmark = "1.2.2"
androidxLifecycleLifecycleRuntimeCompose = "2.7.0"
androidxNavigationNavigationCompose = "2.7.6"
+androidxProfileinstallerProfileinstaller = "1.3.1"
androidxRoom = "2.6.1"
androidxTest = "1.5.0"
androidxTestExtJunitKtx = "1.1.5"
@@ -57,6 +58,7 @@ androidx-datastore-datastore-preferences = { group = "androidx.datastore", name
androidx-hilt-hilt-navigation-compose = { group = "androidx.hilt", name = "hilt-navigation-compose", version.ref = "androidxHiltHiltNavigationCompose" }
androidx-lifecycle-lifecycle-runtime-compose = { group = "androidx.lifecycle", name = "lifecycle-runtime-compose", version.ref = "androidxLifecycleLifecycleRuntimeCompose" }
androidx-navigation-navigation-compose = { group = "androidx.navigation", name = "navigation-compose", version.ref = "androidxNavigationNavigationCompose" }
+androidx-profileinstaller-profileinstaller = { group = "androidx.profileinstaller", name = "profileinstaller", version.ref = "androidxProfileinstallerProfileinstaller" }
androidx-room-runtime = { group = "androidx.room", name = "room-runtime", version.ref = "androidxRoom" }
androidx-room-ktx = { group = "androidx.room", name = "room-ktx", version.ref = "androidxRoom" }
androidx-room-compiler = { group = "androidx.room", name = "room-compiler", version.ref = "androidxRoom" }