Skip to content

Commit 206ff24

Browse files
authored
Set up baseline profiles (#700)
1 parent 0e6407a commit 206ff24

File tree

14 files changed

+29880
-18
lines changed

14 files changed

+29880
-18
lines changed

.gitattributes

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
**/schemas/**/*.json linguist-generated=true
22
scripts/gemoji.json linguist-generated=true
3-
**/schema.json linguist-generated=true
3+
**/schema.json linguist-generated=true
4+
**/generated/baselineProfiles/** linguist-generated=true

app/build.gradle.kts

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ plugins {
3939
alias(libs.plugins.anvil)
4040
alias(libs.plugins.ksp)
4141
alias(libs.plugins.bugsnag)
42+
alias(libs.plugins.sqldelight)
43+
alias(libs.plugins.baselineprofile)
4244
// alias(libs.plugins.playPublisher)
4345
}
4446

@@ -111,7 +113,7 @@ android {
111113
}
112114
splits {
113115
abi {
114-
isEnable = true
116+
isEnable = false // For baseline profile gen - https://issuetracker.google.com/285398001
115117
reset()
116118
include("armeabi-v7a", "arm64-v8a", "x86", "x86_64")
117119
isUniversalApk = true
@@ -458,6 +460,15 @@ androidComponents {
458460
}
459461
}
460462

463+
baselineProfile {
464+
// TODO enable this only when cutting a new release?
465+
// automaticGenerationDuringBuild = true
466+
mergeIntoMain = true
467+
saveInSrc = true
468+
dexLayoutOptimization = true
469+
from(projects.benchmark.dependencyProject)
470+
}
471+
461472
dependencies {
462473
ksp(libs.circuit.codegen)
463474

@@ -506,6 +517,7 @@ dependencies {
506517
implementation(libs.androidx.palette)
507518
implementation(libs.androidx.preference)
508519
implementation(libs.androidx.preferenceKtx)
520+
implementation(libs.androidx.profileinstaller)
509521
implementation(libs.androidx.window)
510522
implementation(libs.apollo.httpcache)
511523
implementation(libs.apollo.normalizedCache)
@@ -575,8 +587,8 @@ dependencies {
575587
debugImplementation(libs.retrofit.moshi)
576588
debugImplementation(projects.libraries.retrofitconverters)
577589

578-
kapt(project(":libraries:tooling:spi-multibinds-validator"))
579-
kapt(project(":libraries:tooling:spi-visualizer"))
590+
kaptDebug(project(":libraries:tooling:spi-multibinds-validator"))
591+
kaptDebug(project(":libraries:tooling:spi-visualizer"))
580592

581593
testImplementation(libs.misc.debug.flipper)
582594
testImplementation(libs.misc.debug.flipperNetwork)

app/src/main/generated/baselineProfiles/startup-prof.txt

Lines changed: 14858 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/src/main/kotlin/io/sweers/catchup/home/HomeScreen.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package io.sweers.catchup.home
22

33
import android.content.res.Configuration
4+
import androidx.activity.compose.ReportDrawnWhen
45
import androidx.annotation.ColorRes
56
import androidx.compose.animation.Animatable
67
import androidx.compose.animation.core.tween
@@ -334,6 +335,7 @@ fun Home(state: HomeScreen.State, modifier: Modifier = Modifier) {
334335
)
335336
}
336337
}
338+
var contentComposed by remember { mutableStateOf(false) }
337339

338340
HorizontalPager(
339341
modifier = Modifier.weight(1f),
@@ -342,6 +344,7 @@ fun Home(state: HomeScreen.State, modifier: Modifier = Modifier) {
342344
state = pagerState,
343345
verticalAlignment = Alignment.Top,
344346
) { page ->
347+
contentComposed = true
345348
CompositionLocalProvider(
346349
LocalScrollToTop provides scrollToTop.takeIf { pagerState.currentPage == page },
347350
LocalServiceThemeColor provides colorCache[page],
@@ -352,6 +355,7 @@ fun Home(state: HomeScreen.State, modifier: Modifier = Modifier) {
352355
)
353356
}
354357
}
358+
ReportDrawnWhen { contentComposed }
355359
}
356360
}
357361
}

app/src/release/generated/baselineProfiles/startup-prof.txt

Lines changed: 14856 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

benchmark/build.gradle.kts

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
// Copyright (C) 2022 Slack Technologies, LLC
2+
// SPDX-License-Identifier: Apache-2.0
3+
import com.android.build.api.dsl.ManagedVirtualDevice
4+
5+
plugins {
6+
id("com.android.test")
7+
kotlin("android")
8+
alias(libs.plugins.baselineprofile)
9+
}
10+
11+
// TODO fix these in SGP
12+
java {
13+
toolchain {
14+
languageVersion.set(JavaLanguageVersion.of(libs.versions.jdk.get().toInt()))
15+
}
16+
}
17+
18+
tasks.withType<JavaCompile>().configureEach {
19+
options.release.set(libs.versions.jvmTarget.get().toInt())
20+
}
21+
22+
android {
23+
compileSdk = 34 // TODO add in SGP
24+
namespace = "io.sweers.catchup.benchmark"
25+
defaultConfig {
26+
minSdk = 28 // TODO add in SGP
27+
targetSdk = 34
28+
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
29+
}
30+
31+
testOptions.managedDevices.devices {
32+
create<ManagedVirtualDevice>("pixel6Api31") {
33+
device = "Pixel 6"
34+
apiLevel = 31
35+
systemImageSource = "aosp"
36+
}
37+
}
38+
39+
targetProjectPath = ":app"
40+
experimentalProperties["android.experimental.r8.dex-startup-optimization"] = true
41+
}
42+
43+
baselineProfile {
44+
// This specifies the managed devices to use that you run the tests on. The default
45+
// is none.
46+
managedDevices += "pixel6Api31"
47+
48+
// This enables using connected devices to generate profiles. The default is true.
49+
// When using connected devices, they must be rooted or API 33 and higher.
50+
useConnectedDevices = false
51+
52+
// Set to true to see the emulator, useful for debugging. Only enabled locally
53+
enableEmulatorDisplay = false
54+
}
55+
56+
dependencies {
57+
implementation(libs.androidx.compose.runtime)
58+
implementation(libs.androidx.test.ext.junit)
59+
implementation(libs.androidx.test.espresso.core)
60+
implementation(libs.androidx.test.uiautomator)
61+
implementation(libs.androidx.benchmark.macro.junit)
62+
implementation(libs.androidx.profileinstaller)
63+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
3+
4+
<queries>
5+
<package android:name="io.sweers.catchup" />
6+
</queries>
7+
</manifest>
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright (C) 2022 Slack Technologies, LLC
2+
// SPDX-License-Identifier: Apache-2.0
3+
package dev.zacsweers.catchup.benchmark
4+
5+
import androidx.benchmark.macro.junit4.BaselineProfileRule
6+
import org.junit.Rule
7+
import org.junit.Test
8+
9+
class BaselineProfileGenerator {
10+
@get:Rule val baselineProfileRule = BaselineProfileRule()
11+
12+
@Test
13+
fun startupBaselineProfile() =
14+
baselineProfileRule.collect(
15+
packageName = "io.sweers.catchup",
16+
// Iteration values recommended by AndroidX folks
17+
maxIterations = 15,
18+
stableIterations = 3,
19+
includeInStartupProfile = true,
20+
profileBlock = { startActivityAndWait() }
21+
)
22+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright (C) 2022 Slack Technologies, LLC
2+
// SPDX-License-Identifier: Apache-2.0
3+
package dev.zacsweers.catchup.benchmark
4+
5+
import androidx.benchmark.macro.StartupMode
6+
import androidx.benchmark.macro.StartupTimingMetric
7+
import androidx.benchmark.macro.junit4.MacrobenchmarkRule
8+
import androidx.test.ext.junit.runners.AndroidJUnit4
9+
import org.junit.Rule
10+
import org.junit.Test
11+
import org.junit.runner.RunWith
12+
13+
@RunWith(AndroidJUnit4::class)
14+
class StartupBenchmark {
15+
@get:Rule val benchmarkRule = MacrobenchmarkRule()
16+
17+
@Test
18+
fun startup() =
19+
benchmarkRule.measureRepeated(
20+
packageName = "io.sweers.catchup",
21+
metrics = listOf(StartupTimingMetric()),
22+
iterations = 5,
23+
startupMode = StartupMode.COLD
24+
) {
25+
pressHome()
26+
startActivityAndWait()
27+
}
28+
}

gradle.properties

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ kotlin.build.report.output=file,build_scan
3535
org.gradle.unsafe.configuration-cache=true
3636

3737
android.useAndroidX=true
38-
android.suppressUnsupportedOptionWarnings=android.suppressUnsupportedOptionWarnings,android.enableR8.fullMode,android.namespacedRClass,android.useMinimalKeepRules,android.disableResourceValidation
38+
android.suppressUnsupportedOptionWarnings=android.suppressUnsupportedOptionWarnings,android.enableR8.fullMode,android.namespacedRClass,android.useMinimalKeepRules,android.disableResourceValidation,android.experimental.testOptions.managedDevices.setupTimeoutMinutes
39+
android.experimental.testOptions.managedDevices.setupTimeoutMinutes=20
3940
android.suppressUnsupportedCompileSdk=34
4041

4142
android.namespacedRClass=true

gradle/libs.versions.toml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ accompanist = "0.31.5-beta"
33
agp = "8.2.0-alpha14"
44
androidx-activity = "1.8.0-alpha06"
55
androidx-core = "1.12.0-beta01"
6+
benchmark = "1.2.0-beta02"
67
compose-material3 = "1.2.0-alpha04"
78
emoji = "1.2.0-alpha03"
89
fragment = "1.7.0-alpha01"
@@ -27,6 +28,7 @@ eithernet = "1.4.1"
2728
espresso = "3.5.1"
2829
flipper = "0.201.0"
2930
jdk = "20"
31+
jvmTarget = "11"
3032
kotlin = "1.9.0"
3133
kotlinx-metadata = "0.6.2"
3234
kotlinx-serialization = "1.5.1"
@@ -53,6 +55,7 @@ anvil = { id = "com.squareup.anvil", version.ref = "anvil" }
5355
agp-application = { id = "com.android.application", version.ref = "agp" }
5456
agp-library = { id = "com.android.library", version.ref = "agp" }
5557
apollo = { id = "com.apollographql.apollo3", version.ref = "apollo" }
58+
baselineprofile = { id = "androidx.baselineprofile", version.ref = "benchmark"}
5659
bugsnag = { id = "com.bugsnag.android.gradle", version = "8.0.1" }
5760
cacheFixPlugin = { id = "org.gradle.android.cache-fix", version = "2.7.2" }
5861
dependencyAnalysis = { id = "com.autonomousapps.dependency-analysis", version = "1.20.0" }
@@ -79,6 +82,8 @@ androidx-activity = { module = "androidx.activity:activity", version.ref = "andr
7982
androidx-activity-compose = { module = "androidx.activity:activity-compose", version.ref = "androidx-activity" }
8083
androidx-appCompat = "androidx.appcompat:appcompat:1.7.0-alpha03"
8184

85+
androidx-benchmark-macro-junit = { module = "androidx.benchmark:benchmark-macro-junit4", version.ref = "benchmark" }
86+
8287
androidx-core = { module = "androidx.core:core", version.ref = "androidx-core" }
8388
androidx-coreKtx = { module = "androidx.core:core-ktx", version.ref = "androidx-core" }
8489

@@ -116,6 +121,12 @@ androidx-compose-material-material3 = { module = "androidx.compose.material3:mat
116121
androidx-compose-material-material3-windowSizeClass = { module = "androidx.compose.material3:material3-window-size-class", version.ref = "compose-material3" }
117122
androidx-window = { module = "androidx.window:window", version = "1.2.0-beta01" }
118123

124+
androidx-profileinstaller = "androidx.profileinstaller:profileinstaller:1.3.1"
125+
androidx-test-espresso-core = "androidx.test.espresso:espresso-core:3.5.1"
126+
androidx-test-ext-junit = "androidx.test.ext:junit:1.1.5"
127+
androidx-test-monitor = "androidx.test:monitor:1.6.1"
128+
androidx-test-uiautomator = "androidx.test.uiautomator:uiautomator:2.3.0-alpha03"
129+
119130
firebase-core = "com.google.firebase:firebase-core:21.1.1"
120131
firebase-database = "com.google.firebase:firebase-database:20.2.2"
121132

scripts/update-baseline-profiles.sh

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
#!/usr/bin/env bash
2+
set -uo pipefail
3+
4+
# If on CI, add indirect swiftshader arg
5+
gpu_arg=" "
6+
if [[ "${CI:-}" == "true" ]]; then
7+
gpu_arg="-Pandroid.testoptions.manageddevices.emulator.gpu=swiftshader_indirect"
8+
fi
9+
10+
# TODO --unused-only flag for cleaning can't be used because devices appear to be left in a bad state
11+
./gradlew cleanManagedDevices && ./gradlew generateBaselineProfile $gpu_arg

settings-all.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
include(
22
":app",
3+
":benchmark",
34
":libraries:auth",
45
":libraries:base-ui",
56
":libraries:appconfig",

settings.gradle.kts

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,6 @@ pluginManagement {
5353
}
5454

5555
// Maven central
56-
// Specifically Google's maven central mirror:
57-
// https://maven-central.storage.googleapis.com/index.html
58-
maven("https://maven-central.storage-download.googleapis.com/maven2/") {
59-
name = "Maven Central (GCP Mirror)"
60-
}
61-
// Google's mirror is sometimes slow to index new releases, so check central just in case!
6256
mavenCentral()
6357

6458
// Google/Firebase/GMS/Androidx libraries
@@ -171,13 +165,6 @@ dependencyResolutionManagement {
171165
mavenLocal()
172166
}
173167

174-
// Maven central
175-
// Specifically Google's maven central mirror:
176-
// https://maven-central.storage.googleapis.com/index.html
177-
maven("https://maven-central.storage-download.googleapis.com/maven2/") {
178-
name = "Maven Central (GCP Mirror)"
179-
}
180-
// Google's mirror is sometimes slow to index new releases, so check central just in case!
181168
mavenCentral()
182169

183170
// Google/Firebase/GMS/Androidx libraries

0 commit comments

Comments
 (0)