Report total size of Composable methods in benchmarks
Change-Id: I25d81f3e9f4b91715fddb869ac112ce2b2f24d57
diff --git a/src/test/java/com/android/tools/r8/benchmarks/BenchmarkConfig.java b/src/test/java/com/android/tools/r8/benchmarks/BenchmarkConfig.java
index b04a407..b73738e 100644
--- a/src/test/java/com/android/tools/r8/benchmarks/BenchmarkConfig.java
+++ b/src/test/java/com/android/tools/r8/benchmarks/BenchmarkConfig.java
@@ -4,7 +4,6 @@
package com.android.tools.r8.benchmarks;
import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Sets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -12,7 +11,6 @@
import java.util.HashSet;
import java.util.List;
import java.util.Map;
-import java.util.Objects;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@@ -26,20 +24,6 @@
throw new BenchmarkConfigError(
"Inconsistent single/group benchmark setup: " + benchmark + " and " + other);
}
- Set<String> subNames =
- Sets.union(benchmark.getSubBenchmarks().keySet(), other.getSubBenchmarks().keySet());
- for (String subName : subNames) {
- if (!Objects.equals(
- benchmark.getSubBenchmarks().get(subName), other.getSubBenchmarks().get(subName))) {
- throw new BenchmarkConfigError(
- "Inconsistent metrics for sub-benchmark "
- + subName
- + " in benchmarks: "
- + benchmark
- + " and "
- + other);
- }
- }
if (!benchmark.getSuite().equals(other.getSuite())) {
throw new BenchmarkConfigError(
"Inconsistent suite for benchmarks: " + benchmark + " and " + other);
@@ -182,6 +166,11 @@
return this;
}
+ public Builder measureComposableCodeSize() {
+ metrics.add(BenchmarkMetric.ComposableCodeSize);
+ return this;
+ }
+
public Builder measureWarmup() {
measureWarmup = true;
return this;
diff --git a/src/test/java/com/android/tools/r8/benchmarks/BenchmarkResultsCollection.java b/src/test/java/com/android/tools/r8/benchmarks/BenchmarkResultsCollection.java
index da3f3d2..8fc8508 100644
--- a/src/test/java/com/android/tools/r8/benchmarks/BenchmarkResultsCollection.java
+++ b/src/test/java/com/android/tools/r8/benchmarks/BenchmarkResultsCollection.java
@@ -24,22 +24,25 @@
@Override
public void addRuntimeResult(long result) {
throw new BenchmarkConfigError(
- "Unexpected attempt to add a runtime result to a the root of a benchmark with"
- + " sub-benchmarks");
+ "Unexpected attempt to add a result to a the root of a benchmark with sub-benchmarks");
}
@Override
public void addCodeSizeResult(long result) {
throw new BenchmarkConfigError(
- "Unexpected attempt to add a runtime result to a the root of a benchmark with"
- + " sub-benchmarks");
+ "Unexpected attempt to add a result to a the root of a benchmark with sub-benchmarks");
+ }
+
+ @Override
+ public void addComposableCodeSizeResult(long result) {
+ throw new BenchmarkConfigError(
+ "Unexpected attempt to add a result to a the root of a benchmark with sub-benchmarks");
}
@Override
public void addResourceSizeResult(long result) {
throw new BenchmarkConfigError(
- "Unexpected attempt to add a runtime result to a the root of a benchmark with"
- + " sub-benchmarks");
+ "Unexpected attempt to add a result to a the root of a benchmark with sub-benchmarks");
}
@Override
diff --git a/src/test/java/com/android/tools/r8/benchmarks/BenchmarkResultsSingle.java b/src/test/java/com/android/tools/r8/benchmarks/BenchmarkResultsSingle.java
index e15dffb..ad6b1b3 100644
--- a/src/test/java/com/android/tools/r8/benchmarks/BenchmarkResultsSingle.java
+++ b/src/test/java/com/android/tools/r8/benchmarks/BenchmarkResultsSingle.java
@@ -9,13 +9,15 @@
import it.unimi.dsi.fastutil.longs.LongList;
import java.io.PrintStream;
import java.util.Set;
+import java.util.function.LongConsumer;
public class BenchmarkResultsSingle implements BenchmarkResults {
- private String name;
+ private final String name;
private final Set<BenchmarkMetric> metrics;
private final LongList runtimeResults = new LongArrayList();
private final LongList codeSizeResults = new LongArrayList();
+ private final LongList composableCodeSizeResults = new LongArrayList();
public BenchmarkResultsSingle(String name, Set<BenchmarkMetric> metrics) {
this.name = name;
@@ -30,6 +32,10 @@
return codeSizeResults;
}
+ public LongList getComposableCodeSizeResults() {
+ return composableCodeSizeResults;
+ }
+
public LongList getRuntimeResults() {
return runtimeResults;
}
@@ -47,6 +53,15 @@
}
@Override
+ public void addComposableCodeSizeResult(long result) {
+ verifyMetric(
+ BenchmarkMetric.ComposableCodeSize,
+ metrics.contains(BenchmarkMetric.ComposableCodeSize),
+ true);
+ composableCodeSizeResults.add(result);
+ }
+
+ @Override
public void addResourceSizeResult(long result) {
addCodeSizeResult(result);
}
@@ -78,6 +93,10 @@
BenchmarkMetric.CodeSize,
metrics.contains(BenchmarkMetric.CodeSize),
!codeSizeResults.isEmpty());
+ verifyMetric(
+ BenchmarkMetric.ComposableCodeSize,
+ metrics.contains(BenchmarkMetric.ComposableCodeSize),
+ !composableCodeSizeResults.isEmpty());
}
private void printRunTime(long duration) {
@@ -89,6 +108,11 @@
System.out.println(BenchmarkResults.prettyMetric(name, BenchmarkMetric.CodeSize, "" + bytes));
}
+ private void printComposableCodeSize(long bytes) {
+ System.out.println(
+ BenchmarkResults.prettyMetric(name, BenchmarkMetric.ComposableCodeSize, "" + bytes));
+ }
+
@Override
public void printResults(ResultMode mode, boolean failOnCodeSizeDifferences) {
verifyConfigAndResults();
@@ -97,6 +121,13 @@
long result = mode == ResultMode.SUM ? sum : sum / runtimeResults.size();
printRunTime(result);
}
+ printCodeSizeResults(codeSizeResults, failOnCodeSizeDifferences, this::printCodeSize);
+ printCodeSizeResults(
+ composableCodeSizeResults, failOnCodeSizeDifferences, this::printComposableCodeSize);
+ }
+
+ private static void printCodeSizeResults(
+ LongList codeSizeResults, boolean failOnCodeSizeDifferences, LongConsumer printer) {
if (!codeSizeResults.isEmpty()) {
long size = codeSizeResults.getLong(0);
if (failOnCodeSizeDifferences) {
@@ -107,7 +138,7 @@
}
}
}
- printCodeSize(size);
+ printer.accept(size);
}
}
diff --git a/src/test/java/com/android/tools/r8/benchmarks/BenchmarkResultsSingleAdapter.java b/src/test/java/com/android/tools/r8/benchmarks/BenchmarkResultsSingleAdapter.java
index 55936d7..68d6fb8 100644
--- a/src/test/java/com/android/tools/r8/benchmarks/BenchmarkResultsSingleAdapter.java
+++ b/src/test/java/com/android/tools/r8/benchmarks/BenchmarkResultsSingleAdapter.java
@@ -22,6 +22,10 @@
(codeSizeResult, iteration) -> {
JsonObject resultObject = new JsonObject();
resultObject.addProperty("code_size", codeSizeResult);
+ if (!result.getComposableCodeSizeResults().isEmpty()) {
+ resultObject.addProperty(
+ "composable_code_size", result.getComposableCodeSizeResults().getLong(iteration));
+ }
resultObject.addProperty("runtime", result.getRuntimeResults().getLong(iteration));
resultsArray.add(resultObject);
});
diff --git a/src/test/java/com/android/tools/r8/benchmarks/BenchmarkResultsWarmup.java b/src/test/java/com/android/tools/r8/benchmarks/BenchmarkResultsWarmup.java
index 1a4e33c..19c1de8 100644
--- a/src/test/java/com/android/tools/r8/benchmarks/BenchmarkResultsWarmup.java
+++ b/src/test/java/com/android/tools/r8/benchmarks/BenchmarkResultsWarmup.java
@@ -13,6 +13,7 @@
private final String name;
private final LongList runtimeResults = new LongArrayList();
private long codeSizeResult = -1;
+ private long composableCodeSizeResult = -1;
private long resourceSizeResult = -1;
public BenchmarkResultsWarmup(String name) {
@@ -36,6 +37,20 @@
}
@Override
+ public void addComposableCodeSizeResult(long result) {
+ if (composableCodeSizeResult == -1) {
+ composableCodeSizeResult = result;
+ }
+ if (composableCodeSizeResult != result) {
+ throw new RuntimeException(
+ "Unexpected Composable code size difference: "
+ + result
+ + " and "
+ + composableCodeSizeResult);
+ }
+ }
+
+ @Override
public void addResourceSizeResult(long result) {
if (resourceSizeResult == -1) {
resourceSizeResult = result;
diff --git a/src/test/java/com/android/tools/r8/benchmarks/appdumps/AppDumpBenchmarkBuilder.java b/src/test/java/com/android/tools/r8/benchmarks/appdumps/AppDumpBenchmarkBuilder.java
index 9454d6e..1f087c1 100644
--- a/src/test/java/com/android/tools/r8/benchmarks/appdumps/AppDumpBenchmarkBuilder.java
+++ b/src/test/java/com/android/tools/r8/benchmarks/appdumps/AppDumpBenchmarkBuilder.java
@@ -20,7 +20,12 @@
import com.android.tools.r8.benchmarks.BenchmarkTarget;
import com.android.tools.r8.dump.CompilerDump;
import com.android.tools.r8.dump.DumpOptions;
+import com.android.tools.r8.keepanno.annotations.AnnotationPattern;
+import com.android.tools.r8.keepanno.annotations.KeepEdge;
+import com.android.tools.r8.keepanno.annotations.KeepItemKind;
+import com.android.tools.r8.keepanno.annotations.KeepTarget;
import java.io.IOException;
+import java.lang.annotation.RetentionPolicy;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
@@ -31,6 +36,18 @@
public class AppDumpBenchmarkBuilder {
+ @KeepEdge(
+ consequences =
+ @KeepTarget(
+ kind = KeepItemKind.ONLY_METHODS,
+ methodAnnotatedByClassName = "androidx.compose.runtime.Composable",
+ constraints = {},
+ constrainAnnotations =
+ @AnnotationPattern(
+ name = "androidx.compose.runtime.Composable",
+ retention = RetentionPolicy.CLASS)))
+ static class KeepComposableAnnotations {}
+
public static AppDumpBenchmarkBuilder builder() {
return new AppDumpBenchmarkBuilder();
}
@@ -99,6 +116,7 @@
.addDependency(dumpDependency)
.measureRunTime()
.measureCodeSize()
+ .measureComposableCodeSize()
.setTimeout(10, TimeUnit.MINUTES)
.build();
}
@@ -158,6 +176,10 @@
return name + "Code";
}
+ private String nameForComposableCodePart() {
+ return name + "ComposableCode";
+ }
+
private String nameForLibraryPart() {
return name + "Library";
}
@@ -210,6 +232,16 @@
options -> options.getOpenClosedInterfacesOptions().suppressAllOpenInterfaces());
}
+ private static ThrowableConsumer<? super R8FullTestBuilder>
+ getKeepComposableAnnotationsConfiguration() {
+ return testBuilder ->
+ testBuilder
+ .addProgramClasses(KeepComposableAnnotations.class)
+ .addKeepClassAndMembersRules("androidx.compose.runtime.Composable")
+ .addKeepRuntimeVisibleAnnotations()
+ .enableExperimentalKeepAnnotations();
+ }
+
private static BenchmarkMethod runR8(
AppDumpBenchmarkBuilder builder, ThrowableConsumer<? super R8FullTestBuilder> configuration) {
return internalRunR8(builder, false, configuration);
@@ -253,6 +285,12 @@
})
.apply(configuration)
.applyIf(
+ environment
+ .getConfig()
+ .getMetrics()
+ .contains(BenchmarkMetric.ComposableCodeSize),
+ getKeepComposableAnnotationsConfiguration())
+ .applyIf(
enableResourceShrinking,
b ->
b.enableOptimizedShrinking()
@@ -264,9 +302,14 @@
results.getSubResults(builder.nameForRuntimePart()))
.benchmarkCodeSize(
results.getSubResults(builder.nameForCodePart()))
+ .benchmarkComposableCodeSize(
+ results.getSubResults(builder.nameForComposableCodePart()))
.benchmarkResourceSize(
results.getSubResults(builder.nameForResourcePart())),
- r -> r.benchmarkCompile(results).benchmarkCodeSize(results));
+ r ->
+ r.benchmarkCompile(results)
+ .benchmarkCodeSize(results)
+ .benchmarkComposableCodeSize(results));
});
}
diff --git a/src/test/testbase/java/com/android/tools/r8/R8TestCompileResult.java b/src/test/testbase/java/com/android/tools/r8/R8TestCompileResult.java
index 172fb2b..7a4f1ba 100644
--- a/src/test/testbase/java/com/android/tools/r8/R8TestCompileResult.java
+++ b/src/test/testbase/java/com/android/tools/r8/R8TestCompileResult.java
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8;
+import static com.android.tools.r8.utils.codeinspector.Matchers.isPresent;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
@@ -12,6 +13,8 @@
import com.android.tools.r8.androidresources.AndroidResourceTestingUtils.ResourceTableInspector;
import com.android.tools.r8.benchmarks.BenchmarkResults;
import com.android.tools.r8.dexsplitter.SplitterTestBase.SplitRunner;
+import com.android.tools.r8.errors.Unimplemented;
+import com.android.tools.r8.graph.ProgramMethod;
import com.android.tools.r8.metadata.R8BuildMetadata;
import com.android.tools.r8.profile.art.model.ExternalArtProfile;
import com.android.tools.r8.profile.art.utils.ArtProfileInspector;
@@ -19,13 +22,14 @@
import com.android.tools.r8.shaking.ProguardConfigurationRule;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.FileUtils;
+import com.android.tools.r8.utils.IntBox;
import com.android.tools.r8.utils.InternalOptions;
import com.android.tools.r8.utils.ThrowingBiConsumer;
import com.android.tools.r8.utils.ThrowingConsumer;
import com.android.tools.r8.utils.ZipUtils;
import com.android.tools.r8.utils.codeinspector.ClassSubject;
import com.android.tools.r8.utils.codeinspector.CodeInspector;
-import com.android.tools.r8.utils.codeinspector.Matchers;
+import com.android.tools.r8.utils.codeinspector.FoundClassSubject;
import com.android.tools.r8.utils.graphinspector.GraphInspector;
import java.io.IOException;
import java.io.UncheckedIOException;
@@ -266,21 +270,18 @@
throws IOException {
assert getBackend() == runtime.getBackend();
ClassSubject mainClassSubject = inspector().clazz(SplitRunner.class);
- assertThat(
- "Did you forget a keep rule for the main method?", mainClassSubject, Matchers.isPresent());
+ assertThat("Did you forget a keep rule for the main method?", mainClassSubject, isPresent());
assertThat(
"Did you forget a keep rule for the main method?",
mainClassSubject.mainMethod(),
- Matchers.isPresent());
+ isPresent());
ClassSubject mainFeatureClassSubject = featureInspector(feature).clazz(mainFeatureClass);
assertThat(
- "Did you forget a keep rule for the run method?",
- mainFeatureClassSubject,
- Matchers.isPresent());
+ "Did you forget a keep rule for the run method?", mainFeatureClassSubject, isPresent());
assertThat(
"Did you forget a keep rule for the run method?",
mainFeatureClassSubject.uniqueMethodWithOriginalName("run"),
- Matchers.isPresent());
+ isPresent());
String[] args = new String[2 + featureDependencies.length];
args[0] = mainFeatureClassSubject.getFinalName();
args[1] = feature.toString();
@@ -319,4 +320,28 @@
results.addCodeSizeResult(applicationSizeWithFeatures);
return self();
}
+
+ @Override
+ public R8TestCompileResult benchmarkComposableCodeSize(BenchmarkResults results)
+ throws IOException {
+ if (!features.isEmpty()) {
+ throw new Unimplemented();
+ }
+ CodeInspector inspector = inspector();
+ ClassSubject annotationClassSubject = inspector.clazz("androidx.compose.runtime.Composable");
+ assertThat(annotationClassSubject, isPresent());
+ IntBox composableCodeSize = new IntBox();
+ for (FoundClassSubject classSubject : inspector.allClasses()) {
+ for (ProgramMethod method : classSubject.getDexProgramClass().directProgramMethods()) {
+ if (method
+ .getAnnotations()
+ .hasAnnotation(annotationClassSubject.getDexProgramClass().getType())) {
+ composableCodeSize.increment(
+ method.getDefinition().getCode().asDexCode().codeSizeInBytes());
+ }
+ }
+ }
+ results.addComposableCodeSizeResult(composableCodeSize.get());
+ return self();
+ }
}
diff --git a/src/test/testbase/java/com/android/tools/r8/TestBuilder.java b/src/test/testbase/java/com/android/tools/r8/TestBuilder.java
index a7c2cd8..5f9d323 100644
--- a/src/test/testbase/java/com/android/tools/r8/TestBuilder.java
+++ b/src/test/testbase/java/com/android/tools/r8/TestBuilder.java
@@ -50,7 +50,7 @@
return self();
}
- public T applyIf(boolean value, ThrowableConsumer<T> consumer) {
+ public T applyIf(boolean value, ThrowableConsumer<? super T> consumer) {
T self = self();
if (value) {
consumer.acceptWithRuntimeException(self);
diff --git a/src/test/testbase/java/com/android/tools/r8/TestCompileResult.java b/src/test/testbase/java/com/android/tools/r8/TestCompileResult.java
index 8f32eae..1f50960 100644
--- a/src/test/testbase/java/com/android/tools/r8/TestCompileResult.java
+++ b/src/test/testbase/java/com/android/tools/r8/TestCompileResult.java
@@ -20,6 +20,7 @@
import com.android.tools.r8.ToolHelper.ProcessResult;
import com.android.tools.r8.benchmarks.BenchmarkResults;
import com.android.tools.r8.debug.DebugTestConfig;
+import com.android.tools.r8.errors.Unimplemented;
import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.origin.Origin;
import com.android.tools.r8.utils.AndroidApiLevel;
@@ -721,4 +722,9 @@
results.addCodeSizeResult(app.applicationSize());
return self();
}
+
+ public CR benchmarkComposableCodeSize(BenchmarkResults results)
+ throws IOException, ResourceException {
+ throw new Unimplemented();
+ }
}
diff --git a/src/test/testbase/java/com/android/tools/r8/benchmarks/BenchmarkMetric.java b/src/test/testbase/java/com/android/tools/r8/benchmarks/BenchmarkMetric.java
index 62bc0ba..abf93ce 100644
--- a/src/test/testbase/java/com/android/tools/r8/benchmarks/BenchmarkMetric.java
+++ b/src/test/testbase/java/com/android/tools/r8/benchmarks/BenchmarkMetric.java
@@ -6,6 +6,7 @@
public enum BenchmarkMetric {
RunTimeRaw,
CodeSize,
+ ComposableCodeSize,
StartupTime;
public String getDartType() {
diff --git a/src/test/testbase/java/com/android/tools/r8/benchmarks/BenchmarkResults.java b/src/test/testbase/java/com/android/tools/r8/benchmarks/BenchmarkResults.java
index 9dcfa97..a925368 100644
--- a/src/test/testbase/java/com/android/tools/r8/benchmarks/BenchmarkResults.java
+++ b/src/test/testbase/java/com/android/tools/r8/benchmarks/BenchmarkResults.java
@@ -13,6 +13,8 @@
// Append a code size result. This is always assumed to be identical if called multiple times.
void addCodeSizeResult(long result);
+ void addComposableCodeSizeResult(long result);
+
// Append a resource size result. This is always assumed to be identical if called multiple times.
void addResourceSizeResult(long result);
diff --git a/tools/run_benchmark.py b/tools/run_benchmark.py
index 6bf0882..f01535f 100755
--- a/tools/run_benchmark.py
+++ b/tools/run_benchmark.py
@@ -18,7 +18,9 @@
utils.GRADLE_TASK_TESTBASE_WITH_APPLY_MAPPING_JAR,
utils.GRADLE_TASK_TEST_DEPS_JAR
]
-GOLEM_BUILD_TARGETS = [utils.GRADLE_TASK_R8LIB] + GOLEM_BUILD_TARGETS_TESTS
+GOLEM_BUILD_TARGETS = [
+ utils.GRADLE_TASK_R8LIB, utils.GRADLE_TASK_KEEP_ANNO_JAR
+] + GOLEM_BUILD_TARGETS_TESTS
def get_golem_resource_path(benchmark):
@@ -46,6 +48,13 @@
required=True,
# These should 1:1 with benchmarks/BenchmarkTarget.java
choices=['d8', 'r8-full', 'r8-force', 'r8-compat'])
+ result.add_argument(
+ '--debug-agent',
+ '--debug_agent',
+ help=
+ 'Enable Java debug agent and suspend compilation (default disabled)',
+ default=False,
+ action='store_true')
result.add_argument('--nolib',
'--no-lib',
'--no-r8lib',
@@ -119,7 +128,8 @@
utils.GRADLE_TASK_TEST_JAR, utils.GRADLE_TASK_TEST_DEPS_JAR,
utils.GRADLE_TASK_TEST_UNZIP_TESTBASE
]
- buildTargets = [utils.GRADLE_TASK_R8] + testBuildTargets
+ buildTargets = [utils.GRADLE_TASK_R8, utils.GRADLE_TASK_KEEP_ANNO_JAR
+ ] + testBuildTargets
r8jar = utils.R8_JAR
testjars = [
utils.R8_TESTS_JAR, utils.R8_TESTS_DEPS_JAR, utils.R8_TESTBASE_JAR
@@ -157,7 +167,8 @@
cmd = [
jdk.GetJavaExecutable(jdkhome), '-Xms8g', '-Xmx8g',
'-XX:+TieredCompilation', '-XX:TieredStopAtLevel=4',
- '-DBENCHMARK_IGNORE_CODE_SIZE_DIFFERENCES'
+ '-DBENCHMARK_IGNORE_CODE_SIZE_DIFFERENCES',
+ f'-DBUILD_PROP_KEEPANNO_RUNTIME_PATH={utils.REPO_ROOT}/d8_r8/keepanno/build/classes/java/main'
]
if options.enable_assertions:
cmd.append('-ea')
@@ -175,6 +186,10 @@
if options.output:
cmd.append(f'-DBENCHMARK_OUTPUT={options.output}')
cmd.extend(['-cp', ':'.join([r8jar] + testjars)])
+ if options.debug_agent:
+ cmd.append(
+ '-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=*:5005'
+ )
cmd.extend([
'com.android.tools.r8.benchmarks.BenchmarkMainEntryRunner',
options.benchmark,