feat: restore baseline profile generation job

This commit is contained in:
Harsh Shandilya
2026-01-13 06:26:55 +05:30
parent b29785a5fc
commit 7ee0071da6
11 changed files with 257 additions and 1 deletions
+9
View File
@@ -17,6 +17,7 @@ plugins {
id("kotlin-parcelize")
alias(libs.plugins.aboutlibraries)
alias(libs.plugins.modulegraphassert)
alias(libs.plugins.baselineprofile)
alias(libs.plugins.licensee)
alias(libs.plugins.kotlin.composeCompiler)
alias(libs.plugins.kotlin.serialization)
@@ -34,10 +35,16 @@ android {
signingConfig = signingConfigs["debug"]
isMinifyEnabled = true
}
buildTypes.getByName("release") { baselineProfile.automaticGenerationDuringBuild = true }
}
aboutLibraries.collect.gitHubApiToken = providers.environmentVariable("GITHUB_TOKEN").orNull
baselineProfile {
mergeIntoMain = true
saveInSrc = true
}
licensee {
allow("Apache-2.0")
allow("MIT")
@@ -54,6 +61,8 @@ moduleGraphAssert {
}
dependencies {
baselineProfile(projects.benchmark)
implementation(platform(libs.okhttp.bom))
implementation(libs.aboutLibraries.compose.core)
implementation(libs.aboutLibraries.core)
+1
View File
@@ -0,0 +1 @@
/build
+62
View File
@@ -0,0 +1,62 @@
/*
* Copyright © Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/
@file:Suppress("UnstableApiUsage")
plugins {
alias(libs.plugins.android.test)
id("dev.msfjarvis.claw.kotlin-android")
alias(libs.plugins.baselineprofile)
alias(libs.plugins.dependencyAnalysis)
}
android {
namespace = "dev.msfjarvis.claw.benchmark"
compileSdk = 36
defaultConfig {
minSdk = 28
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
create("benchmark") {
isDebuggable = true
signingConfig = signingConfigs["debug"]
matchingFallbacks += "release"
}
}
testOptions {
managedDevices {
localDevices.create("pixel6Api31") {
device = "Pixel 6"
apiLevel = 31
systemImageSource = "aosp-atd"
}
}
}
targetProjectPath = ":android"
}
baselineProfile {
managedDevices += "pixel6Api31"
useConnectedDevices = false
enableEmulatorDisplay = false
}
dependencies {
implementation(libs.androidx.benchmark.macro.junit4)
implementation(libs.androidx.profileinstaller)
implementation(libs.androidx.test.core)
implementation(libs.androidx.test.espresso.core)
implementation(libs.androidx.test.ext.junit)
implementation(libs.androidx.test.rules)
implementation(libs.androidx.test.runner)
implementation(libs.androidx.test.uiautomator)
implementation(libs.androidx.tracing.perfetto)
implementation(libs.androidx.tracing.perfetto.binary)
}
+11
View File
@@ -0,0 +1,11 @@
<!--
~ Copyright © Harsh Shandilya.
~ Use of this source code is governed by an MIT-style
~ license that can be found in the LICENSE file or at
~ https://opensource.org/licenses/MIT.
-->
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<queries>
<package android:name="dev.msfjarvis.claw.android" />
</queries>
</manifest>
@@ -0,0 +1,67 @@
/*
* Copyright © Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/
package dev.msfjarvis.claw.android.benchmark
import androidx.benchmark.macro.BaselineProfileMode
import androidx.benchmark.macro.CompilationMode
import androidx.benchmark.macro.FrameTimingMetric
import androidx.benchmark.macro.StartupMode
import androidx.benchmark.macro.StartupTimingMetric
import androidx.benchmark.macro.junit4.MacrobenchmarkRule
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import org.junit.Before
import org.junit.Rule
import org.junit.Test
class BaselineProfileBenchmark {
@get:Rule val benchmarkRule = MacrobenchmarkRule()
private lateinit var device: UiDevice
@Before
fun setUp() {
val instrumentation = InstrumentationRegistry.getInstrumentation()
device = UiDevice.getInstance(instrumentation)
}
@Test
fun noCompilation() {
exploreUI(CompilationMode.None())
}
@Test
fun fullyCompiled() {
exploreUI(CompilationMode.Full())
}
@Test
fun baselineProfile() {
exploreUI(CompilationMode.Partial(baselineProfileMode = BaselineProfileMode.Require))
}
private fun exploreUI(compilationMode: CompilationMode) {
benchmarkRule.measureRepeated(
packageName = PACKAGE_NAME,
metrics = listOf(FrameTimingMetric(), StartupTimingMetric()),
compilationMode = compilationMode,
startupMode = StartupMode.COLD,
iterations = 10,
) {
device.executeShellCommand("pm clear $PACKAGE_NAME")
startActivityAndWait()
device.waitForIdle()
device.savePosts()
device.exploreScreens()
device.returnToHottestScreen()
}
}
}
@@ -0,0 +1,45 @@
/*
* Copyright © Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/
package dev.msfjarvis.claw.android.benchmark
import androidx.benchmark.macro.junit4.BaselineProfileRule
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import org.junit.Before
import org.junit.Rule
import org.junit.Test
class BaselineProfileGenerator {
@get:Rule val baselineProfileRule = BaselineProfileRule()
private lateinit var device: UiDevice
@Before
fun setUp() {
val instrumentation = InstrumentationRegistry.getInstrumentation()
device = UiDevice.getInstance(instrumentation)
}
@Test
fun generateBaselineProfile() =
baselineProfileRule.collect(
packageName = PACKAGE_NAME,
maxIterations = 8,
includeInStartupProfile = true,
) {
device.executeShellCommand("pm clear $PACKAGE_NAME")
startActivityAndWait()
device.waitForIdle()
device.savePosts()
device.exploreScreens()
device.returnToHottestScreen()
}
}
@@ -0,0 +1,43 @@
/*
* Copyright © Harsh Shandilya.
* Use of this source code is governed by an MIT-style
* license that can be found in the LICENSE file or at
* https://opensource.org/licenses/MIT.
*/
package dev.msfjarvis.claw.android.benchmark
import androidx.test.uiautomator.By
import androidx.test.uiautomator.BySelector
import androidx.test.uiautomator.UiDevice
import androidx.test.uiautomator.UiObject2
import androidx.test.uiautomator.Until
const val PACKAGE_NAME = "dev.msfjarvis.claw.android"
private const val AWAIT_TIMEOUT = 10_000L
private const val SAVE_BUTTON_ID = "save_button"
private const val NAV_ID_HOTTEST = "HOTTEST"
private const val NAV_ID_NEWEST = "NEWEST"
private const val NAV_ID_SAVED = "SAVED"
fun UiDevice.savePosts() {
waitForObject(By.res(SAVE_BUTTON_ID)).click()
}
fun UiDevice.exploreScreens() {
listOf(NAV_ID_HOTTEST, NAV_ID_NEWEST, NAV_ID_SAVED).forEach { tag ->
waitForObject(By.res(tag)).click()
waitForIdle()
}
}
fun UiDevice.returnToHottestScreen() {
waitForObject(By.res(NAV_ID_HOTTEST)).click()
}
private fun UiDevice.waitForObject(selector: BySelector, timeout: Long = AWAIT_TIMEOUT): UiObject2 {
if (wait(Until.hasObject(selector), timeout)) {
return findObject(selector)
}
error("Object with selector [$selector] not found")
}
@@ -41,6 +41,7 @@ class SentryPlugin : Plugin<Project> {
autoUploadNativeSymbols.set(true)
includeNativeSources.set(false)
ignoredVariants.set(emptySet())
ignoredBuildTypes.set(setOf("benchmark"))
ignoredFlavors.set(emptySet())
tracingInstrumentation {
enabled.set(true)
+1
View File
@@ -8,5 +8,6 @@ plugins {
id("dev.msfjarvis.claw.spotless")
id("dev.msfjarvis.claw.versions")
id("dev.msfjarvis.claw.kotlin-common")
alias(libs.plugins.android.test) apply false
alias(libs.plugins.dependencyAnalysis)
}
+16
View File
@@ -1,6 +1,7 @@
[versions]
aboutLibraries = "14.0.0-a02"
agp = "9.1.0-alpha04"
androidx-test = "1.7.0"
annotation = "1.9.1"
coil3 = "3.3.0"
compose-animation = "1.11.0-alpha02"
@@ -8,6 +9,7 @@ compose-foundation = "1.11.0-alpha02"
compose-icons = "1.7.8"
compose-material3 = "1.5.0-alpha11"
compose-runtime = "1.11.0-alpha02"
benchmark = "1.5.0-alpha01"
compose-ui = "1.11.0-alpha02"
coroutines = "1.10.2"
datastore = "1.2.0"
@@ -28,6 +30,8 @@ sentry-sdk = "8.29.0"
serialization = "1.10.0-RC"
sqldelight = "2.2.1"
sqlite = "2.6.2"
tracing = "1.3.0"
tracing-perfetto = "1.0.0"
workmanager = "2.11.0"
[libraries]
@@ -40,6 +44,7 @@ android-security-lints = "com.android.security.lint:lint:1.0.4"
androidx-activity = "androidx.activity:activity:1.12.2"
androidx-activity-compose = "androidx.activity:activity-compose:1.12.2"
androidx-annotation = { module = "androidx.annotation:annotation", version.ref = "annotation" }
androidx-benchmark-macro-junit4 = { module = "androidx.benchmark:benchmark-macro-junit4", version.ref = "benchmark" }
androidx-browser = "androidx.browser:browser:1.9.0"
androidx-compose-animation = { module = "androidx.compose.animation:animation", version.ref = "compose-animation" }
androidx-compose-animation-core = { module = "androidx.compose.animation:animation-core", version.ref = "compose-animation" }
@@ -82,6 +87,15 @@ androidx-paging-common = { module = "androidx.paging:paging-common", version.ref
androidx-paging-compose = { module = "androidx.paging:paging-compose", version.ref = "paging" }
androidx-profileinstaller = "androidx.profileinstaller:profileinstaller:1.4.1"
androidx-sqlite = { module = "androidx.sqlite:sqlite", version.ref = "sqlite" }
androidx-test-core = { module = "androidx.test:core", version.ref = "androidx-test" }
androidx-test-espresso-core = "androidx.test.espresso:espresso-core:3.7.0-alpha03"
androidx-test-ext-junit = "androidx.test.ext:junit:1.3.0-alpha03"
androidx-test-rules = { module = "androidx.test:rules", version.ref = "androidx-test" }
androidx-test-runner = { module = "androidx.test:runner", version.ref = "androidx-test" }
androidx-test-uiautomator = "androidx.test.uiautomator:uiautomator:2.4.0-alpha04"
androidx-tracing = { group = "androidx.tracing", name = "tracing-ktx", version.ref = "tracing" }
androidx-tracing-perfetto = { module = "androidx.tracing:tracing-perfetto", version.ref = "tracing-perfetto" }
androidx-tracing-perfetto-binary = { module = "androidx.tracing:tracing-perfetto-binary", version.ref = "tracing-perfetto" }
androidx-work-runtime = { module = "androidx.work:work-runtime", version.ref = "workmanager" }
build-agp = { module = "com.android.tools.build:gradle", version.ref = "agp" }
build-cachefix = "org.gradle.android.cache-fix:org.gradle.android.cache-fix.gradle.plugin:3.0.3"
@@ -155,7 +169,9 @@ kotlin-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect", version.ref =
[plugins]
aboutlibraries = { id = "com.mikepenz.aboutlibraries.plugin.android", version.ref = "aboutLibraries" }
android-lint = { id = "com.android.lint", version.ref = "agp" }
android-test = { id = "com.android.test", version.ref = "agp" }
dependencyAnalysis = "com.autonomousapps.dependency-analysis:3.5.1"
baselineprofile = { id = "androidx.baselineprofile", version.ref = "benchmark" }
kotlin-composeCompiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
ksp = "com.google.devtools.ksp:2.3.4"
+1 -1
View File
@@ -99,4 +99,4 @@ rootProject.name = "Claw"
enableFeaturePreview("TYPESAFE_PROJECT_ACCESSORS")
include("android", "api", "common", "core", "database:core", "database:impl", "model")
include("android", "api", "benchmark", "common", "core", "database:core", "database:impl", "model")