Added support to generate startup-prof.txt in BaselineProfileRule
This PR adds a profile type parameter when generating a baseline
profile. When the profile type is `STARTUP` the generated file is a
startup-prof.txt. The internal format is the same HRF of baseline
profile.
Relnote: Added profile type parameter when generating baseline profiles
Bug: 275093123
Test: ./gradlew :benchmark:integration-tests:baselineprofile-library-consumer:testBaselineProfileGeneration :benchmark:integration-tests:baselineprofile-flavor-consumer:testBaselineProfileGeneration :benchmark:integration-tests:baselineprofile-consumer:testBaselineProfileGeneration :benchmark:benchmark-baseline-profile-gradle-plugin:test
Change-Id: Ie20d730efea37940bf9df519c86cdb29a4074d34
diff --git a/benchmark/benchmark-common/src/main/java/androidx/benchmark/Arguments.kt b/benchmark/benchmark-common/src/main/java/androidx/benchmark/Arguments.kt
index 7af3fa9..8b9c181 100644
--- a/benchmark/benchmark-common/src/main/java/androidx/benchmark/Arguments.kt
+++ b/benchmark/benchmark-common/src/main/java/androidx/benchmark/Arguments.kt
@@ -193,7 +193,7 @@
arguments.getBenchmarkArgument("killProcessDelayMillis")?.toLong() ?: 0L
enableStartupProfiles =
- arguments.getBenchmarkArgument("startupProfiles.enable")?.toBoolean() ?: false
+ arguments.getBenchmarkArgument("startupProfiles.enable")?.toBoolean() ?: true
strictStartupProfiles =
arguments.getBenchmarkArgument("startupProfiles.strict")?.toBoolean() ?: false
diff --git a/benchmark/benchmark-macro-junit4/api/current.txt b/benchmark/benchmark-macro-junit4/api/current.txt
index 3358929..0bcc71e 100644
--- a/benchmark/benchmark-macro-junit4/api/current.txt
+++ b/benchmark/benchmark-macro-junit4/api/current.txt
@@ -4,7 +4,8 @@
@RequiresApi(28) public final class BaselineProfileRule implements org.junit.rules.TestRule {
ctor public BaselineProfileRule();
method public org.junit.runners.model.Statement apply(org.junit.runners.model.Statement base, org.junit.runner.Description description);
- method public void collectBaselineProfile(String packageName, optional int iterations, optional String? outputFilePrefix, optional kotlin.jvm.functions.Function1<? super java.lang.String,java.lang.Boolean>? filterPredicate, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
+ method public void collectBaselineProfile(String packageName, optional int iterations, optional String? outputFilePrefix, optional boolean includeInStartupProfile, optional kotlin.jvm.functions.Function1<? super java.lang.String,java.lang.Boolean>? filterPredicate, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
+ method public void collectBaselineProfile(String packageName, optional int iterations, optional String? outputFilePrefix, optional boolean includeInStartupProfile, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
method public void collectBaselineProfile(String packageName, optional int iterations, optional String? outputFilePrefix, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
method public void collectBaselineProfile(String packageName, optional int iterations, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
method public void collectBaselineProfile(String packageName, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
diff --git a/benchmark/benchmark-macro-junit4/api/public_plus_experimental_current.txt b/benchmark/benchmark-macro-junit4/api/public_plus_experimental_current.txt
index 6b25fae..bd292b7 100644
--- a/benchmark/benchmark-macro-junit4/api/public_plus_experimental_current.txt
+++ b/benchmark/benchmark-macro-junit4/api/public_plus_experimental_current.txt
@@ -4,12 +4,14 @@
@RequiresApi(28) public final class BaselineProfileRule implements org.junit.rules.TestRule {
ctor public BaselineProfileRule();
method public org.junit.runners.model.Statement apply(org.junit.runners.model.Statement base, org.junit.runner.Description description);
- method public void collectBaselineProfile(String packageName, optional int iterations, optional String? outputFilePrefix, optional kotlin.jvm.functions.Function1<? super java.lang.String,java.lang.Boolean>? filterPredicate, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
+ method public void collectBaselineProfile(String packageName, optional int iterations, optional String? outputFilePrefix, optional boolean includeInStartupProfile, optional kotlin.jvm.functions.Function1<? super java.lang.String,java.lang.Boolean>? filterPredicate, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
+ method public void collectBaselineProfile(String packageName, optional int iterations, optional String? outputFilePrefix, optional boolean includeInStartupProfile, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
method public void collectBaselineProfile(String packageName, optional int iterations, optional String? outputFilePrefix, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
method public void collectBaselineProfile(String packageName, optional int iterations, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
method public void collectBaselineProfile(String packageName, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
- method @androidx.benchmark.macro.ExperimentalStableBaselineProfilesApi public void collectStableBaselineProfile(String packageName, int maxIterations, optional int stableIterations, optional String? outputFilePrefix, optional boolean strictStability, optional kotlin.jvm.functions.Function1<? super java.lang.String,java.lang.Boolean>? filterPredicate, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
- method @androidx.benchmark.macro.ExperimentalStableBaselineProfilesApi public void collectStableBaselineProfile(String packageName, int maxIterations, optional int stableIterations, optional String? outputFilePrefix, optional boolean strictStability, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
+ method @androidx.benchmark.macro.ExperimentalStableBaselineProfilesApi public void collectStableBaselineProfile(String packageName, int maxIterations, optional int stableIterations, optional String? outputFilePrefix, optional boolean includeInStartupProfile, optional boolean strictStability, optional kotlin.jvm.functions.Function1<? super java.lang.String,java.lang.Boolean>? filterPredicate, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
+ method @androidx.benchmark.macro.ExperimentalStableBaselineProfilesApi public void collectStableBaselineProfile(String packageName, int maxIterations, optional int stableIterations, optional String? outputFilePrefix, optional boolean includeInStartupProfile, optional boolean strictStability, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
+ method @androidx.benchmark.macro.ExperimentalStableBaselineProfilesApi public void collectStableBaselineProfile(String packageName, int maxIterations, optional int stableIterations, optional String? outputFilePrefix, optional boolean includeInStartupProfile, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
method @androidx.benchmark.macro.ExperimentalStableBaselineProfilesApi public void collectStableBaselineProfile(String packageName, int maxIterations, optional int stableIterations, optional String? outputFilePrefix, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
method @androidx.benchmark.macro.ExperimentalStableBaselineProfilesApi public void collectStableBaselineProfile(String packageName, int maxIterations, optional int stableIterations, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
method @androidx.benchmark.macro.ExperimentalStableBaselineProfilesApi public void collectStableBaselineProfile(String packageName, int maxIterations, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
diff --git a/benchmark/benchmark-macro-junit4/api/restricted_current.txt b/benchmark/benchmark-macro-junit4/api/restricted_current.txt
index 3358929..0bcc71e 100644
--- a/benchmark/benchmark-macro-junit4/api/restricted_current.txt
+++ b/benchmark/benchmark-macro-junit4/api/restricted_current.txt
@@ -4,7 +4,8 @@
@RequiresApi(28) public final class BaselineProfileRule implements org.junit.rules.TestRule {
ctor public BaselineProfileRule();
method public org.junit.runners.model.Statement apply(org.junit.runners.model.Statement base, org.junit.runner.Description description);
- method public void collectBaselineProfile(String packageName, optional int iterations, optional String? outputFilePrefix, optional kotlin.jvm.functions.Function1<? super java.lang.String,java.lang.Boolean>? filterPredicate, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
+ method public void collectBaselineProfile(String packageName, optional int iterations, optional String? outputFilePrefix, optional boolean includeInStartupProfile, optional kotlin.jvm.functions.Function1<? super java.lang.String,java.lang.Boolean>? filterPredicate, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
+ method public void collectBaselineProfile(String packageName, optional int iterations, optional String? outputFilePrefix, optional boolean includeInStartupProfile, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
method public void collectBaselineProfile(String packageName, optional int iterations, optional String? outputFilePrefix, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
method public void collectBaselineProfile(String packageName, optional int iterations, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
method public void collectBaselineProfile(String packageName, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
diff --git a/benchmark/benchmark-macro-junit4/src/main/java/androidx/benchmark/macro/junit4/BaselineProfileRule.kt b/benchmark/benchmark-macro-junit4/src/main/java/androidx/benchmark/macro/junit4/BaselineProfileRule.kt
index b9be975..12dca06 100644
--- a/benchmark/benchmark-macro-junit4/src/main/java/androidx/benchmark/macro/junit4/BaselineProfileRule.kt
+++ b/benchmark/benchmark-macro-junit4/src/main/java/androidx/benchmark/macro/junit4/BaselineProfileRule.kt
@@ -108,6 +108,12 @@
* @param outputFilePrefix An optional file name prefix used when creating the output
* file with the contents of the human readable baseline profile.
* For example: `outputFilePrefix-baseline-prof.txt`
+ * @param includeInStartupProfile determines whether the generated profile should be also used
+ * as a startup profile. A startup profile is utilized during the build process in order to
+ * determine which classes are needed in the primary dex to optimize the startup time. This
+ * flag should be used only for startup flows, such as main application startup pre and post
+ * login or other entry points of the app. Note that methods collected in a startup profiles
+ * are also utilized for baseline profiles.
* @param filterPredicate Function used to filter individual rules / lines of the baseline
* profile. By default, no filters are applied. Note that this works only when the target
* application's code is not obfuscated.
@@ -118,6 +124,7 @@
packageName: String,
iterations: Int = 3,
outputFilePrefix: String? = null,
+ includeInStartupProfile: Boolean = false,
filterPredicate: ((String) -> Boolean)? = null,
profileBlock: MacrobenchmarkScope.() -> Unit
) {
@@ -125,6 +132,7 @@
uniqueName = outputFilePrefix ?: currentDescription.toUniqueName(),
packageName = packageName,
iterations = iterations,
+ includeInStartupProfile = includeInStartupProfile,
filterPredicate = filterPredicate,
profileBlock = profileBlock
)
@@ -141,6 +149,12 @@
* @param outputFilePrefix An optional file name prefix used when creating the output
* file with the contents of the human readable baseline profile.
* For example: `outputFilePrefix-baseline-prof.txt`
+ * @param includeInStartupProfile determines whether the generated profile should be also used
+ * as a startup profile. A startup profile is utilized during the build process in order to
+ * determine which classes are needed in the primary dex to optimize the startup time. This
+ * flag should be used only for startup flows, such as main application startup pre and post
+ * login or other entry points of the app. Note that methods collected in a startup profiles
+ * are also utilized for baseline profiles.
* @param strictStability Enforce if the generated profile was stable
* @param filterPredicate Function used to filter individual rules / lines of the baseline
* profile. By default, no filters are applied. Note that this works only when the target
@@ -154,6 +168,7 @@
maxIterations: Int,
stableIterations: Int = 3,
outputFilePrefix: String? = null,
+ includeInStartupProfile: Boolean = false,
strictStability: Boolean = false,
filterPredicate: ((String) -> Boolean)? = null,
profileBlock: MacrobenchmarkScope.() -> Unit
@@ -163,6 +178,7 @@
packageName = packageName,
stableIterations = stableIterations,
maxIterations = maxIterations,
+ includeInStartupProfile = includeInStartupProfile,
strictStability = strictStability,
filterPredicate = filterPredicate,
profileBlock = profileBlock
diff --git a/benchmark/benchmark-macro/api/restricted_current.txt b/benchmark/benchmark-macro/api/restricted_current.txt
index 2176d91..a5eae3b 100644
--- a/benchmark/benchmark-macro/api/restricted_current.txt
+++ b/benchmark/benchmark-macro/api/restricted_current.txt
@@ -10,8 +10,8 @@
}
public final class BaselineProfilesKt {
- method @RequiresApi(28) @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static void collectStableBaselineProfile(String uniqueName, String packageName, int stableIterations, int maxIterations, optional boolean strictStability, kotlin.jvm.functions.Function1<? super java.lang.String,java.lang.Boolean>? filterPredicate, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
- method @RequiresApi(28) @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static void collectStableBaselineProfile(String uniqueName, String packageName, int stableIterations, int maxIterations, kotlin.jvm.functions.Function1<? super java.lang.String,java.lang.Boolean>? filterPredicate, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
+ method @RequiresApi(28) @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static void collectStableBaselineProfile(String uniqueName, String packageName, int stableIterations, int maxIterations, optional boolean strictStability, boolean includeInStartupProfile, kotlin.jvm.functions.Function1<? super java.lang.String,java.lang.Boolean>? filterPredicate, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
+ method @RequiresApi(28) @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public static void collectStableBaselineProfile(String uniqueName, String packageName, int stableIterations, int maxIterations, boolean includeInStartupProfile, kotlin.jvm.functions.Function1<? super java.lang.String,java.lang.Boolean>? filterPredicate, kotlin.jvm.functions.Function1<? super androidx.benchmark.macro.MacrobenchmarkScope,kotlin.Unit> profileBlock);
}
@RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP_PREFIX) public final class BatteryCharge {
diff --git a/benchmark/benchmark-macro/src/androidTest/java/androidx/benchmark/macro/StartupProfilesTest.kt b/benchmark/benchmark-macro/src/androidTest/java/androidx/benchmark/macro/StartupProfilesTest.kt
deleted file mode 100644
index f99856a..0000000
--- a/benchmark/benchmark-macro/src/androidTest/java/androidx/benchmark/macro/StartupProfilesTest.kt
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Copyright 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package androidx.benchmark.macro
-
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SmallTest
-import org.junit.Assert.assertEquals
-import org.junit.Test
-import org.junit.runner.RunWith
-
-@RunWith(AndroidJUnit4::class)
-@SmallTest
-class StartupProfilesTest {
- @Test
- fun startupProfiles() {
- // https://youtrack.jetbrains.com/issue/KT-2425
- val dollar = "$"
- val profile = """
- Landroidx/Foo/Bar;
- Lfoo/bar/Baz$dollar<Suffix>;
- HSPLjava/io/DataOutputStream;->writeByte(I)V+]Ljava/io/OutputStream;missing_types
- """.trimIndent()
-
- val startupRules = startupProfile(profile, includeStartupOnly = false)
- val expectedRules = """
- SLandroidx/Foo/Bar;
- SLfoo/bar/Baz;
- SLjava/io/DataOutputStream;
- """.trimIndent()
- assertEquals(expectedRules, startupRules)
- }
-
- @Test
- fun startupProfiles_includeStartupOnly() {
- // https://youtrack.jetbrains.com/issue/KT-2425
- val dollar = "$"
- val profile = """
- Landroidx/Foo/Bar;
- Lfoo/bar/Baz$dollar<Suffix>;
- HSPLjava/io/DataOutputStream;->writeByte(I)V+]Ljava/io/OutputStream;missing_types
- HPLandroidx/startup/AppInitializer;->**(**)**
- """.trimIndent()
-
- val startupRules = startupProfile(profile, includeStartupOnly = true)
- val expectedRules = """
- SLandroidx/Foo/Bar;
- SLfoo/bar/Baz;
- SLjava/io/DataOutputStream;
- """.trimIndent()
- assertEquals(expectedRules, startupRules)
- }
-}
diff --git a/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/BaselineProfiles.kt b/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/BaselineProfiles.kt
index 6a31a42..e41a947 100644
--- a/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/BaselineProfiles.kt
+++ b/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/BaselineProfiles.kt
@@ -41,6 +41,7 @@
uniqueName: String,
packageName: String,
iterations: Int = 3,
+ includeInStartupProfile: Boolean,
filterPredicate: ((String) -> Boolean)?,
profileBlock: MacrobenchmarkScope.() -> Unit,
) {
@@ -84,7 +85,13 @@
// Filter
val profile = filterProfileRulesToTargetP(unfilteredProfile, sortRules = true)
// Report
- reportResults(profile, filterPredicate, uniqueName, startTime)
+ reportResults(
+ profile = profile,
+ filterPredicate = filterPredicate,
+ uniqueFilePrefix = uniqueName,
+ startTime = startTime,
+ includeInStartupProfile = includeInStartupProfile
+ )
} finally {
killProcessBlock.invoke()
}
@@ -104,6 +111,7 @@
stableIterations: Int,
maxIterations: Int,
strictStability: Boolean = false,
+ includeInStartupProfile: Boolean,
filterPredicate: ((String) -> Boolean)?,
profileBlock: MacrobenchmarkScope.() -> Unit
) {
@@ -188,7 +196,13 @@
}
val profile = filterProfileRulesToTargetP(lastProfile, sortRules = true)
- reportResults(profile, filterPredicate, uniqueName, startTime)
+ reportResults(
+ profile = profile,
+ filterPredicate = filterPredicate,
+ uniqueFilePrefix = uniqueName,
+ startTime = startTime,
+ includeInStartupProfile = includeInStartupProfile
+ )
} finally {
killProcessBlock.invoke()
}
@@ -231,53 +245,41 @@
profile: String,
filterPredicate: ((String) -> Boolean)?,
uniqueFilePrefix: String,
- startTime: Long
+ startTime: Long,
+ includeInStartupProfile: Boolean
) {
- // Build a startup profile
- var startupProfile: String? = null
- if (Arguments.enableStartupProfiles) {
- startupProfile =
- startupProfile(profile, includeStartupOnly = Arguments.strictStartupProfiles)
- }
-
// Filter profile if necessary based on filters
val filteredProfile = applyPackageFilters(profile, filterPredicate)
// Write a file with a timestamp to be able to disambiguate between runs with the same
// unique name.
- val fileName = "$uniqueFilePrefix-baseline-prof.txt"
- val absolutePath = Outputs.writeFile(fileName, "baseline-profile") {
- it.writeText(filteredProfile)
- }
- var startupProfilePath: String? = null
- if (startupProfile != null) {
- val startupProfileFileName = "$uniqueFilePrefix-startup-prof.txt"
- startupProfilePath = Outputs.writeFile(startupProfileFileName, "startup-profile") {
- it.writeText(startupProfile)
+ val (fileName, reportKey, tsFileName) =
+ if (includeInStartupProfile && Arguments.enableStartupProfiles) {
+ arrayOf(
+ "$uniqueFilePrefix-startup-prof.txt",
+ "startup-profile",
+ "$uniqueFilePrefix-startup-prof-${Outputs.dateToFileName()}.txt"
+ )
+ } else {
+ arrayOf(
+ "$uniqueFilePrefix-baseline-prof.txt",
+ "baseline-profile",
+ "$uniqueFilePrefix-baseline-prof-${Outputs.dateToFileName()}.txt"
+ )
}
- }
- val tsFileName = "$uniqueFilePrefix-baseline-prof-${Outputs.dateToFileName()}.txt"
+
+ val absolutePath = Outputs.writeFile(fileName, reportKey) { it.writeText(filteredProfile) }
val tsAbsolutePath = Outputs.writeFile(tsFileName, "baseline-profile-ts") {
Log.d(TAG, "Pull Baseline Profile with: `adb pull \"${it.absolutePath}\" .`")
it.writeText(filteredProfile)
}
- var tsStartupAbsolutePath: String? = null
- if (startupProfile != null) {
- val tsStartupFileName = "$uniqueFilePrefix-startup-prof-${Outputs.dateToFileName()}.txt"
- tsStartupAbsolutePath = Outputs.writeFile(tsStartupFileName, "startup-profile-ts") {
- Log.d(TAG, "Pull Startup Profile with: `adb pull \"${it.absolutePath}\" .`")
- it.writeText(startupProfile)
- }
- }
val totalRunTime = System.nanoTime() - startTime
val results = Summary(
totalRunTime = totalRunTime,
profilePath = absolutePath,
- profileTsPath = tsAbsolutePath,
- startupProfilePath = startupProfilePath,
- startupTsProfilePath = tsStartupAbsolutePath
+ profileTsPath = tsAbsolutePath
)
InstrumentationResults.instrumentationReport {
val summary = summaryRecord(results)
@@ -411,21 +413,7 @@
""".trimIndent()
)
- // Link to a path with timestamp to prevent studio from caching the file
- val startupTsProfilePath = record.startupTsProfilePath
- if (!startupTsProfilePath.isNullOrBlank()) {
- val startupRelativePath = Outputs.relativePathFor(startupTsProfilePath)
- .replace("(", "\\(")
- .replace(")", "\\)")
- summary.append("\n").append(
- """
- Startup profile [results](file://$startupRelativePath)
- """.trimIndent()
- )
- }
-
// Add commands that can be used to pull these files.
-
summary.append("\n")
.append("\n")
.append(
@@ -434,18 +422,6 @@
adb ${deviceSpecifier}pull "${record.profilePath}" .
""".trimIndent()
)
-
- val startupProfilePath = record.startupProfilePath
- if (!startupProfilePath.isNullOrBlank()) {
- summary.append("\n")
- .append("\n")
- .append(
- """
- To copy the startup profile use:
- adb ${deviceSpecifier}pull "${record.startupProfilePath}" .
- """.trimIndent()
- )
- }
return summary.toString()
}
@@ -471,14 +447,4 @@
val totalRunTime: Long,
val profilePath: String,
val profileTsPath: String,
- val startupProfilePath: String? = null,
- val startupTsProfilePath: String? = null
-) {
- init {
- if (startupProfilePath.isNullOrBlank()) {
- require(startupTsProfilePath.isNullOrBlank())
- } else {
- require(!startupTsProfilePath.isNullOrBlank())
- }
- }
-}
+)
diff --git a/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/StartupProfiles.kt b/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/StartupProfiles.kt
deleted file mode 100644
index 8b50582..0000000
--- a/benchmark/benchmark-macro/src/main/java/androidx/benchmark/macro/StartupProfiles.kt
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright 2022 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-@file:RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
-
-package androidx.benchmark.macro
-
-import androidx.annotation.RestrictTo
-
-private val PROFILE_RULE_REGEX = "(H?S?P?)L([^$;]*)(.*)".toRegex()
-
-/**
- * Builds a startup profile for a given baseline profile.
- *
- * This startup profile can be used for dex layout optimizations.
- */
-fun startupProfile(profile: String, includeStartupOnly: Boolean = false): String {
- val rules = profile.lines().mapNotNull { rule ->
- when (val result = PROFILE_RULE_REGEX.find(rule)) {
- null -> null
- else -> {
- val (flags, classPrefix, _) = result.destructured
- // Empty flags are indicative that the class needs to be aggressively preloaded
- // Therefore the class belongs in the primary dex.
- val isStartup = flags.isEmpty() || flags.contains("S")
- if (includeStartupOnly && !isStartup) {
- null
- } else {
- "SL$classPrefix;"
- }
- }
- }
- }
- val ruleSet = mutableSetOf<String>()
- val startupRules = mutableListOf<String>()
- // Try and keep the same order
- rules.forEach { rule ->
- if (!ruleSet.contains(rule)) {
- ruleSet += rule
- startupRules += rule
- }
- }
- return startupRules.joinToString(separator = "\n")
-}
diff --git a/benchmark/integration-tests/macrobenchmark/src/androidTest/java/androidx/benchmark/integration/macrobenchmark/BaselineProfileRuleTest.kt b/benchmark/integration-tests/macrobenchmark/src/androidTest/java/androidx/benchmark/integration/macrobenchmark/BaselineProfileRuleTest.kt
index 4c36dffb3..9bbca93 100644
--- a/benchmark/integration-tests/macrobenchmark/src/androidTest/java/androidx/benchmark/integration/macrobenchmark/BaselineProfileRuleTest.kt
+++ b/benchmark/integration-tests/macrobenchmark/src/androidTest/java/androidx/benchmark/integration/macrobenchmark/BaselineProfileRuleTest.kt
@@ -40,6 +40,8 @@
@get:Rule
val baselineRule = BaselineProfileRule()
+ private val filterRegex = "^.*L${PACKAGE_NAME.replace(".", "/")}".toRegex()
+
@Test
fun appNotInstalled() {
val error = assertFailsWith<AssertionError> {
@@ -64,9 +66,7 @@
// Collects the baseline profile
baselineRule.collectBaselineProfile(
packageName = PACKAGE_NAME,
- filterPredicate = {
- it.contains("^.*L${PACKAGE_NAME.replace(".", "/")}".toRegex())
- },
+ filterPredicate = { it.contains(filterRegex) },
profileBlock = {
assertEquals(expectedIteration++, iteration)
startActivityAndWait(Intent(ACTION))
@@ -75,8 +75,13 @@
)
assertEquals(3, expectedIteration)
+ // Note: this name is automatically generated starting from class and method name,
+ // according to the patter `<class>_<method>-baseline-prof.txt`. Changes for class and
+ // method names should be reflected here in order for the test to succeed.
+ val baselineProfileOutputFileName = "BaselineProfileRuleTest_filter-baseline-prof.txt"
+
// Asserts the output of the baseline profile
- val lines = File(Outputs.outputDirectory, BASELINE_PROFILE_OUTPUT_FILE_NAME).readLines()
+ val lines = File(Outputs.outputDirectory, baselineProfileOutputFileName).readLines()
assertThat(lines).containsExactly(
"HSPLandroidx/benchmark/integration/macrobenchmark/target/EmptyActivity;" +
"-><init>()V",
@@ -86,16 +91,44 @@
)
}
+ @Test
+ fun profileType() {
+ assumeTrue(Build.VERSION.SDK_INT >= 33 || Shell.isSessionRooted())
+
+ data class TestConfig(val includeInStartupProfile: Boolean, val outputFileName: String)
+
+ arrayOf(
+ TestConfig(true, "BaselineProfileRuleTest_profileType-startup-prof.txt"),
+ TestConfig(false, "BaselineProfileRuleTest_profileType-baseline-prof.txt"),
+ ).forEach { (includeInStartupProfile, outputFilename) ->
+
+ // Collects the baseline profile
+ baselineRule.collectBaselineProfile(
+ packageName = PACKAGE_NAME,
+ filterPredicate = { it.contains(filterRegex) },
+ includeInStartupProfile = includeInStartupProfile,
+ profileBlock = {
+ startActivityAndWait(Intent(ACTION))
+ device.waitForIdle()
+ }
+ )
+
+ // Asserts the output of the baseline profile
+ val lines = File(Outputs.outputDirectory, outputFilename).readLines()
+ assertThat(lines).containsExactly(
+ "HSPLandroidx/benchmark/integration/macrobenchmark/target/EmptyActivity;" +
+ "-><init>()V",
+ "HSPLandroidx/benchmark/integration/macrobenchmark/target/EmptyActivity;" +
+ "->onCreate(Landroid/os/Bundle;)V",
+ "Landroidx/benchmark/integration/macrobenchmark/target/EmptyActivity;",
+ )
+ }
+ }
+
companion object {
private const val PACKAGE_NAME =
"androidx.benchmark.integration.macrobenchmark.target"
private const val ACTION =
"androidx.benchmark.integration.macrobenchmark.target.EMPTY_ACTIVITY"
-
- // Note: this name is automatically generated starting from class and method name,
- // according to the patter `<class>_<method>-baseline-prof.txt`. Changes for class and
- // method names should be reflected here in order for the test to succeed.
- private const val BASELINE_PROFILE_OUTPUT_FILE_NAME =
- "BaselineProfileRuleTest_filter-baseline-prof.txt"
}
}