Generate profile automatically with release builds

Change-Id: I2fef03733b7ea277a7747f7f0c2d179a69ba2d79
wk/baseline-profile-experiments
Wojtek Kaliciński 2 years ago
parent d0ba51efec
commit 2d56a80cb2

1
.gitignore vendored

@ -16,6 +16,7 @@ build/
# Local configuration file (sdk path, etc) # Local configuration file (sdk path, etc)
local.properties local.properties
secrets.properties
# Eclipse project files # Eclipse project files
.classpath .classpath

@ -1,3 +1,6 @@
import com.android.build.gradle.internal.component.ApkCreationConfig
import com.android.build.gradle.internal.tasks.factory.dependsOn
/* /*
* Copyright 2021 The Android Open Source Project * Copyright 2021 The Android Open Source Project
* *
@ -119,3 +122,52 @@ configurations.configureEach {
force("org.objenesis:objenesis:2.6") force("org.objenesis:objenesis:2.6")
} }
} }
configurations {
create("releaseBaselineProfile") {
isCanBeConsumed = false
isCanBeResolved = true
attributes {
attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category.LIBRARY))
attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage.JAVA_RUNTIME))
attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, objects.named("baseline-profile"))
}
}
}
dependencies {
"releaseBaselineProfile"(project(":benchmark"))
}
val copyBpTask = tasks.register<GenerateBaselineProfTask>("copyBaselineProfile") {
inputArtifact.set(configurations.getByName("releaseBaselineProfile").incoming.artifacts.resolvedArtifacts.map {
layout.projectDirectory.file(it.single().file.absolutePath)
})
baselineProfTxt.set(layout.projectDirectory.file("src/main/baseline-prof.txt"))
}
afterEvaluate {
tasks.named("mergeDemoReleaseArtProfile").dependsOn(copyBpTask)
tasks.named("mergeProdReleaseArtProfile").dependsOn(copyBpTask)
}
abstract class GenerateBaselineProfTask : DefaultTask() {
@get:Inject
abstract val layout: ProjectLayout
@get:InputFile
abstract val inputArtifact: RegularFileProperty
@get:OutputFile
abstract val baselineProfTxt: RegularFileProperty
@TaskAction
fun execute() {
baselineProfTxt.asFile.get().delete()
inputArtifact.get().asFile.copyTo(baselineProfTxt.asFile.get())
}
}

File diff suppressed because it is too large Load Diff

@ -13,16 +13,19 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
import com.android.build.api.dsl.ManagedVirtualDevice
import com.android.build.gradle.internal.tasks.factory.dependsOn
import com.google.samples.apps.nowinandroid.Flavor import com.google.samples.apps.nowinandroid.Flavor
import com.google.samples.apps.nowinandroid.FlavorDimension import com.google.samples.apps.nowinandroid.FlavorDimension
import com.google.samples.apps.nowinandroid.configureFlavors import com.google.samples.apps.nowinandroid.configureFlavors
import org.jetbrains.kotlin.util.capitalizeDecapitalize.capitalizeAsciiOnly
plugins { plugins {
id("nowinandroid.android.test") id("nowinandroid.android.test")
} }
android { android {
namespace = "com.google.samples.apps.nowinandroid.benchmark" namespace = "com.google.samples.apps.nowinandroid.benchmarking"
defaultConfig { defaultConfig {
minSdk = 23 minSdk = 23
@ -45,13 +48,49 @@ android {
} }
} }
// Use the same flavor dimensions as the application to allow generating Baseline Profiles on prod, // Use the same flavor dimensions as the application to allow generating Baseline Profiles on prod,
// which is more close to what will be shipped to users (no fake data), but has ability to run the // which is more close to what will be shipped to users (no fake data), but has ability to run the
// benchmarks on demo, so we benchmark on stable data. // benchmarks on demo, so we benchmark on stable data.
configureFlavors(this) configureFlavors(this)
flavorDimensions += "benchmark"
productFlavors {
create("macro") {
dimension = "benchmark"
testInstrumentationRunnerArguments["androidx.benchmark.enabledRules"] = "Macrobenchmark"
}
create("baseline") {
dimension = "benchmark"
testInstrumentationRunnerArguments["androidx.benchmark.enabledRules"] = "BaselineProfile"
}
}
targetProjectPath = ":app" targetProjectPath = ":app"
experimentalProperties["android.experimental.self-instrumenting"] = true experimentalProperties["android.experimental.self-instrumenting"] = true
testOptions {
managedDevices {
devices {
create<ManagedVirtualDevice>("AospAtd30") {
// Use device profiles you typically see in Android Studio.
device = "Pixel 2"
// ATDs currently support only API level 30.
apiLevel = 31
// You can also specify "google-atd" if you require Google Play Services.
systemImageSource = "aosp"
}
create<ManagedVirtualDevice>("GoogleAtd30") {
// Use device profiles you typically see in Android Studio.
device = "Pixel 2"
// ATDs currently support only API level 30.
apiLevel = 30
// You can also specify "google-atd" if you require Google Play Services.
systemImageSource = "google-atd"
}
}
}
}
} }
dependencies { dependencies {
@ -69,4 +108,47 @@ androidComponents {
beforeVariants { beforeVariants {
it.enable = it.buildType == "benchmark" it.enable = it.buildType == "benchmark"
} }
beforeVariants (selector()
.withBuildType("benchmark")
.withFlavor(Flavor.prod.dimension.name to Flavor.prod.name)
.withFlavor("benchmark" to "baseline")) {
val capitalName = it.name.capitalizeAsciiOnly()
val task = tasks.register<Copy>("baselineProfileFor${capitalName}") {
dependsOn("AospAtd30${capitalName}AndroidTest")
from(
buildDir.resolve("outputs/" +
"managed_device_android_test_additional_output/" +
"flavors/" +
"${it.flavorName}/" +
"AospAtd30/" +
"BaselineProfileGenerator_generate-baseline-prof.txt")
)
destinationDir = buildDir.resolve("outputs/baselineProfile")
rename {
"baseline-prof.txt"
}
}
configurations {
println("creating baselineProfile$capitalName")
create("baselineProfile$capitalName") {
isCanBeConsumed = true
isCanBeResolved = false
attributes {
attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category.LIBRARY))
attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage.JAVA_RUNTIME))
attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, objects.named("baseline-profile"))
}
}
}
artifacts {
add("baselineProfile$capitalName", task.map {
it.outputs.files.singleFile.resolve("baseline-prof.txt")
}) {
builtBy(task)
}
}
}
} }

@ -16,10 +16,14 @@
package com.google.samples.apps.nowinandroid package com.google.samples.apps.nowinandroid
import com.google.samples.apps.nowinandroid.benchmark.BuildConfig import com.google.samples.apps.nowinandroid.benchmarking.BuildConfig
/** /**
* Convenience parameter to use proper package name with regards to build type and build flavor. * Convenience parameter to use proper package name with regards to build type and build flavor.
*/ */
const val PACKAGE_NAME = val PACKAGE_NAME = if (BuildConfig.FLAVOR_contentType == "demo") {
"com.google.samples.apps.nowinandroid.${BuildConfig.FLAVOR}.${BuildConfig.BUILD_TYPE}" "com.google.samples.apps.nowinandroid.${BuildConfig.FLAVOR}.${BuildConfig.BUILD_TYPE}"
} else {
"com.google.samples.apps.nowinandroid.${BuildConfig.BUILD_TYPE}"
}

@ -47,26 +47,26 @@ class BaselineProfileGenerator {
startActivityAndWait() startActivityAndWait()
// Scroll the feed critical user journey // Scroll the feed critical user journey
forYouWaitForContent() // forYouWaitForContent()
forYouSelectAuthors() // forYouSelectAuthors()
forYouScrollFeedDownUp() // forYouScrollFeedDownUp()
//
// Navigate to saved screen // // Navigate to saved screen
device.findObject(By.text("Saved")).click() // device.findObject(By.text("Saved")).click()
device.waitForIdle() // device.waitForIdle()
//
bookmarksScrollFeedDownUp() // bookmarksScrollFeedDownUp()
//
// Navigate to interests screen // // Navigate to interests screen
device.findObject(By.text("Interests")).click() // device.findObject(By.text("Interests")).click()
device.waitForIdle() // device.waitForIdle()
//
interestsScrollTopicsDownUp() // interestsScrollTopicsDownUp()
//
// Navigate to people tab // // Navigate to people tab
device.findObject(By.text("People")).click() // device.findObject(By.text("People")).click()
device.waitForIdle() // device.waitForIdle()
//
interestsScrollPeopleDownUp() // interestsScrollPeopleDownUp()
} }
} }

@ -27,16 +27,20 @@ fun MacrobenchmarkScope.forYouWaitForContent() {
} }
fun MacrobenchmarkScope.forYouSelectAuthors() { fun MacrobenchmarkScope.forYouSelectAuthors() {
device.wait(Until.hasObject(By.res("forYou:authors")), 5_000)
val authors = device.findObject(By.res("forYou:authors")) val authors = device.findObject(By.res("forYou:authors"))
// select some authors to show some feed content // select some authors to show some feed content
repeat(3) { index -> repeat(3) { index ->
if (authors.childCount != 0) {
val author = authors.children[index % authors.childCount] val author = authors.children[index % authors.childCount]
author.click() author.click()
}
device.waitForIdle() device.waitForIdle()
} }
} }
fun MacrobenchmarkScope.forYouScrollFeedDownUp() { fun MacrobenchmarkScope.forYouScrollFeedDownUp() {
device.wait(Until.hasObject(By.res("forYou:feed")), 5_000)
val feedList = device.findObject(By.res("forYou:feed")) val feedList = device.findObject(By.res("forYou:feed"))
feedList.fling(Direction.DOWN) feedList.fling(Direction.DOWN)
device.waitForIdle() device.waitForIdle()

@ -30,6 +30,7 @@ android {
} }
secrets { secrets {
propertiesFileName = "secrets.properties"
defaultPropertiesFileName = "secrets.defaults.properties" defaultPropertiesFileName = "secrets.defaults.properties"
} }

@ -1,7 +1,7 @@
[versions] [versions]
accompanist = "0.24.8-beta" accompanist = "0.24.8-beta"
androidDesugarJdkLibs = "1.1.5" androidDesugarJdkLibs = "1.1.5"
androidGradlePlugin = "7.3.0" androidGradlePlugin = "7.3.1"
androidxActivity = "1.6.0" androidxActivity = "1.6.0"
androidxAppCompat = "1.5.1" androidxAppCompat = "1.5.1"
androidxCompose = "1.3.0-beta02" androidxCompose = "1.3.0-beta02"
@ -16,7 +16,7 @@ androidxEspresso = "3.4.0"
androidxHiltNavigationCompose = "1.0.0" androidxHiltNavigationCompose = "1.0.0"
# Skipping version 2.6.0-alpha02 due to https://issuetracker.google.com/249686765 # Skipping version 2.6.0-alpha02 due to https://issuetracker.google.com/249686765
androidxLifecycle = "2.6.0-alpha01" androidxLifecycle = "2.6.0-alpha01"
androidxMacroBenchmark = "1.1.0" androidxMacroBenchmark = "1.2.0-alpha05"
androidxNavigation = "2.5.2" androidxNavigation = "2.5.2"
androidxMetrics = "1.0.0-alpha03" androidxMetrics = "1.0.0-alpha03"
androidxProfileinstaller = "1.2.0" androidxProfileinstaller = "1.2.0"

Loading…
Cancel
Save