Split performance benchmark and baseline profile into separate modules.

This commit is contained in:
Cody Henthorne
2026-02-09 14:39:43 -05:00
committed by Greyson Parrelli
parent 3dd5ad2a8a
commit 4a39c7950f
20 changed files with 97494 additions and 31728 deletions

View File

@@ -20,6 +20,7 @@ plugins {
alias(libs.plugins.ktlint)
alias(libs.plugins.compose.compiler)
alias(libs.plugins.kotlinx.serialization)
alias(benchmarkLibs.plugins.baselineprofile)
id("androidx.navigation.safeargs")
id("kotlin-parcelize")
id("com.squareup.wire")
@@ -60,6 +61,8 @@ val selectableVariants = listOf(
"playProdSpinner",
"playProdCanary",
"playProdPerf",
"playProdMocked",
"playProdNonMinifiedMocked",
"playProdBenchmark",
"playProdInstrumentation",
"playProdRelease",
@@ -359,6 +362,16 @@ android {
buildConfigField("boolean", "TRACING_ENABLED", "true")
}
create("mocked") {
initWith(getByName("debug"))
isDefault = false
isDebuggable = false
isMinifyEnabled = true
matchingFallbacks += "debug"
buildConfigField("String", "BUILD_VARIANT_TYPE", "\"Benchmark\"")
buildConfigField("boolean", "TRACING_ENABLED", "true")
}
create("canary") {
initWith(getByName("debug"))
isDefault = false
@@ -507,6 +520,18 @@ android {
}
}
sourceSets {
getByName("mocked") {
java.srcDir("$projectDir/src/benchmarkShared/java")
manifest.srcFile("$projectDir/src/benchmarkShared/AndroidManifest.xml")
}
getByName("benchmark") {
java.srcDir("$projectDir/src/benchmarkShared/java")
manifest.srcFile("$projectDir/src/benchmarkShared/AndroidManifest.xml")
}
}
applicationVariants.configureEach {
outputs.configureEach {
if (this is com.android.build.gradle.internal.api.BaseVariantOutputImpl) {
@@ -516,6 +541,20 @@ android {
}
}
baselineProfile {
warnings {
disabledVariants = false
}
mergeIntoMain = true
variants.create("mocked") {
from(project(":baseline-profile"))
}
dexLayoutOptimization = false
}
dependencies {
lintChecks(project(":lintchecks"))
ktlintRuleset(libs.ktlint.twitter.compose)

View File

@@ -32,6 +32,8 @@ class BenchmarkSetupActivity : BaseActivity() {
TestMessages.insertIncomingImageMessage(other = recipient, attachmentCount = 1)
TestMessages.insertIncomingImageMessage(other = recipient, attachmentCount = 2, body = "Album")
TestMessages.insertIncomingImageMessage(other = recipient, body = "Test", attachmentCount = 1, failed = true)
TestMessages.insertIncomingTextMessage(other = recipient, body = "Signal message")
TestMessages.insertIncomingTextMessage(other = recipient, body = "Test")
SignalDatabase.messages.setAllMessagesRead()

View File

@@ -96,6 +96,7 @@ object TestMessages {
val message = IncomingMessage(
type = MessageType.NORMAL,
from = other.id,
body = body,
sentTimeMillis = timestamp ?: System.currentTimeMillis(),
serverTimeMillis = timestamp ?: System.currentTimeMillis(),
receivedTimeMillis = timestamp ?: System.currentTimeMillis(),

File diff suppressed because it is too large Load Diff

1
baseline-profile/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/build

View File

@@ -0,0 +1,76 @@
plugins {
id("com.android.test")
alias(libs.plugins.jetbrains.kotlin.android)
alias(benchmarkLibs.plugins.baselineprofile)
}
android {
namespace = "org.signal.baselineprofile"
compileSdk {
version = release(36)
}
compileOptions {
sourceCompatibility = JavaVersion.toVersion(libs.versions.javaVersion.get())
targetCompatibility = JavaVersion.toVersion(libs.versions.javaVersion.get())
}
kotlinOptions {
jvmTarget = libs.versions.kotlinJvmTarget.get()
}
defaultConfig {
minSdk = 28
targetSdk = 36
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
create("mocked") {
matchingFallbacks += "debug"
isDebuggable = true
}
}
targetProjectPath = ":Signal-Android"
flavorDimensions += listOf("distribution", "environment")
productFlavors {
create("play") { dimension = "distribution" }
create("prod") { dimension = "environment" }
}
testOptions {
managedDevices {
localDevices {
create("api31") {
device = "Pixel 3"
apiLevel = 31
systemImageSource = "aosp"
require64Bit = false
}
}
}
}
}
baselineProfile {
managedDevices += "api31"
useConnectedDevices = false
}
dependencies {
implementation(benchmarkLibs.androidx.test.ext.junit)
implementation(benchmarkLibs.espresso.core)
implementation(benchmarkLibs.uiautomator)
implementation(benchmarkLibs.androidx.benchmark.macro)
}
androidComponents {
beforeVariants(selector().all()) {
if (it.flavorName != "playProd" && it.buildType != "mocked") {
it.enable = false
}
}
}

View File

@@ -0,0 +1 @@
<manifest />

View File

@@ -1,11 +1,14 @@
package org.thoughtcrime.benchmark
package org.signal.baselineprofile
import androidx.annotation.RequiresApi
import androidx.benchmark.macro.junit4.BaselineProfileRule
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.LargeTest
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.By
import androidx.test.uiautomator.Until
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
/**
* WARNING! THIS WILL WIPE YOUR SIGNAL INSTALL
@@ -14,8 +17,10 @@ import org.junit.Test
* - start the app
* - open a conversation
*/
@RequiresApi(28)
@RunWith(AndroidJUnit4::class)
@LargeTest
class BaselineProfileGenerator {
@get:Rule
val baselineProfileRule = BaselineProfileRule()
@@ -24,13 +29,16 @@ class BaselineProfileGenerator {
var setup = false
baselineProfileRule.collect(
packageName = "org.thoughtcrime.securesms",
includeInStartupProfile = true,
profileBlock = {
if (!setup) {
BenchmarkSetup.setup("cold-start", device)
setup = true
}
pressHome()
startActivityAndWait()
device.findObject(By.textContains("Buddy")).click();
device.findObject(By.textContains("Buddy")).click()
device.wait(Until.hasObject(By.textContains("Signal message")), 10_000L)
device.wait(Until.hasObject(By.textContains("Test")), 5_000L)
}

View File

@@ -0,0 +1,12 @@
package org.signal.baselineprofile
import androidx.test.uiautomator.By
import androidx.test.uiautomator.UiDevice
import androidx.test.uiautomator.Until
object BenchmarkSetup {
fun setup(type: String, device: UiDevice) {
device.executeShellCommand("am start -W -n org.thoughtcrime.securesms/org.signal.benchmark.BenchmarkSetupActivity --es setup-type $type")
device.wait(Until.hasObject(By.textContains("done")), 25_000L)
}
}

View File

@@ -9,4 +9,4 @@ object BenchmarkSetup {
device.executeShellCommand("am start -W -n org.thoughtcrime.securesms/org.signal.benchmark.BenchmarkSetupActivity --es setup-type $type")
device.wait(Until.hasObject(By.textContains("done")), 25_000L)
}
}
}

View File

@@ -1,6 +1,7 @@
package org.thoughtcrime.benchmark
import androidx.annotation.RequiresApi
import androidx.benchmark.macro.BaselineProfileMode
import androidx.benchmark.macro.CompilationMode
import androidx.benchmark.macro.ExperimentalMetricApi
import androidx.benchmark.macro.StartupMode
@@ -30,7 +31,7 @@ class StartupBenchmarks {
@Test
fun coldStartBaselineProfile() {
measureStartup(5, CompilationMode.Partial())
measureStartup(5, CompilationMode.Partial(BaselineProfileMode.Require))
}
@OptIn(ExperimentalMetricApi::class)

View File

@@ -11,6 +11,7 @@ plugins {
alias(libs.plugins.jetbrains.kotlin.jvm) apply false
alias(libs.plugins.compose.compiler) apply false
alias(libs.plugins.ktlint)
alias(benchmarkLibs.plugins.baselineprofile) apply false
}
buildscript {

View File

@@ -1,6 +1,6 @@
org.gradle.jvmargs=-Xmx12g -Xms256m -XX:MaxMetaspaceSize=1g
android.useAndroidX=true
android.experimental.androidTest.numManagedDeviceShards=4
android.experimental.androidTest.numManagedDeviceShards=1
org.gradle.configuration-cache=true
org.gradle.configuration-cache.problems=fail
# We never want to use auto-provisioning, as it breaks reproducible builds.

View File

@@ -3,6 +3,10 @@
[versions]
androidx-test-ext-junit = "1.3.0"
baselineprofile = "1.4.1"
[plugins]
baselineprofile = { id = "androidx.baselineprofile", version.ref = "baselineprofile" }
[libraries]
# Macrobench/Baseline profiles

View File

@@ -572,6 +572,14 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
<sha256 value="3d47c2a0ddb091e84e2a4a57aeeb3d26e9813ac06c2bcdc88c5aca1307041866" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="androidx.benchmark" name="benchmark-baseline-profile-gradle-plugin" version="1.4.1">
<artifact name="benchmark-baseline-profile-gradle-plugin-1.4.1.jar">
<sha256 value="407f9fb4d81f94243948d649ed58b507c1f65e1e5cf58678c4d8ed5d0f02da59" origin="Generated by Gradle"/>
</artifact>
<artifact name="benchmark-baseline-profile-gradle-plugin-1.4.1.module">
<sha256 value="c2ffeb0e07014c49e0a655318c4f1ab7ed2619b016dfd561f1018dd319870630" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="androidx.benchmark" name="benchmark-common" version="1.1.0-beta04">
<artifact name="benchmark-common-1.1.0-beta04.aar">
<md5 value="f49dea87f6be44083ac2cf44d0093367" origin="Generated by Gradle"/>
@@ -616,6 +624,14 @@ https://docs.gradle.org/current/userguide/dependency_verification.html
<sha256 value="33ca76e3546b7930f6a612e0fd403b38804702292391cdaa608cd00ce3a6eed7" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="androidx.benchmark" name="benchmark-gradle-plugin" version="1.4.1">
<artifact name="benchmark-gradle-plugin-1.4.1.jar">
<sha256 value="845d357344e89f439e281ed7902e68c92067f4966772853b2e9acb9854197a7b" origin="Generated by Gradle"/>
</artifact>
<artifact name="benchmark-gradle-plugin-1.4.1.module">
<sha256 value="517fa4c292f3a5f8f759d12661dcf36f579bc4463ed5648562fd1fa1dcbe0753" origin="Generated by Gradle"/>
</artifact>
</component>
<component group="androidx.benchmark" name="benchmark-junit4" version="1.1.0-beta04">
<artifact name="benchmark-junit4-1.1.0-beta04.aar">
<md5 value="c48014ee5ba7553c916c028310d994f0" origin="Generated by Gradle"/>

View File

@@ -109,6 +109,7 @@ include(":demo:camera")
// Testing/Lint modules
include(":lintchecks")
include(":benchmark")
include(":baseline-profile")
include(":microbenchmark")
// App project name