Add R8 partial NowInAndroid benchmark
Bug: b/388742651
Change-Id: Ia5229edf768441c71c607b815eae06f538354ac2
diff --git a/src/main/java/com/android/tools/r8/BaseCommand.java b/src/main/java/com/android/tools/r8/BaseCommand.java
index cc4cffe..e07018d 100644
--- a/src/main/java/com/android/tools/r8/BaseCommand.java
+++ b/src/main/java/com/android/tools/r8/BaseCommand.java
@@ -119,7 +119,15 @@
}
Builder(DiagnosticsHandler handler) {
- this(AndroidApp.builder(new Reporter(handler)));
+ this(AndroidApp.builder(createReporter(handler)));
+ }
+
+ static Reporter createReporter(DiagnosticsHandler handler) {
+ if (handler instanceof Reporter) {
+ return (Reporter) handler;
+ } else {
+ return new Reporter(handler);
+ }
}
Builder(AndroidApp.Builder builder) {
diff --git a/src/main/java/com/android/tools/r8/R8Partial.java b/src/main/java/com/android/tools/r8/R8Partial.java
index dda3e6e..ebca5fa 100644
--- a/src/main/java/com/android/tools/r8/R8Partial.java
+++ b/src/main/java/com/android/tools/r8/R8Partial.java
@@ -172,7 +172,7 @@
// Compile D8 input with D8.
Path d8Output = tmp.resolve("d8-output.zip");
D8Command.Builder d8Builder =
- D8Command.builder()
+ D8Command.builder(options.reporter)
.setMinApiLevel(dump.getBuildProperties().getMinApi())
.addLibraryFiles(dump.getLibraryArchive())
.addClasspathFiles(dump.getClasspathArchive())
@@ -195,6 +195,7 @@
d8InputAppConsumer.accept(d8App);
}
InternalOptions d8Options = d8command.getInternalOptions();
+ options.partialCompilationConfiguration.d8DexOptionsConsumer.accept(d8Options);
assert d8Options.getMinApiLevel().isGreaterThanOrEqualTo(AndroidApiLevel.N)
: "Default interface methods not yet supported";
D8.runInternal(d8App, d8Options, executor);
@@ -251,7 +252,7 @@
Path r8Output = tmp.resolve("r8-output.zip");
R8DataResources r8DataResources = new R8DataResources();
R8Command.Builder r8Builder =
- R8Command.builder()
+ R8Command.builder(options.reporter)
.setMinApiLevel(dump.getBuildProperties().getMinApi())
.addLibraryFiles(dump.getLibraryArchive())
.addClasspathFiles(dump.getClasspathArchive())
@@ -282,6 +283,7 @@
r8InputAppConsumer.accept(r8App);
}
InternalOptions r8Options = r8Command.getInternalOptions();
+ options.partialCompilationConfiguration.r8OptionsConsumer.accept(r8Options);
r8Options.mapConsumer = originalMapConsumer;
r8Options.quiet = true; // Don't write the R8 version.
R8.runInternal(r8App, r8Options, executor);
@@ -291,7 +293,7 @@
// TODO(b/309743298): Handle jumbo string rewriting with PCs in mapping file.
D8Command.Builder mergerBuilder =
- D8Command.builder()
+ D8Command.builder(options.reporter)
.setMinApiLevel(dump.getBuildProperties().getMinApi())
.addLibraryFiles(dump.getLibraryArchive())
.addClasspathFiles(dump.getClasspathArchive())
@@ -302,6 +304,7 @@
D8Command mergeCommand = mergerBuilder.makeCommand();
AndroidApp mergeApp = mergeCommand.getInputApp();
InternalOptions mergeOptions = mergeCommand.getInternalOptions();
+ options.partialCompilationConfiguration.d8MergeOptionsConsumer.accept(mergeOptions);
D8.runInternal(mergeApp, mergeOptions, executor);
// Feed the data resource output by R8 to the output consumer. Keeping this at the end after the
// merge keeps the order of calls to the output consumer closer to full R8.
diff --git a/src/main/java/com/android/tools/r8/utils/R8PartialCompilationConfiguration.java b/src/main/java/com/android/tools/r8/utils/R8PartialCompilationConfiguration.java
index a1c3b2d..2586b2d 100644
--- a/src/main/java/com/android/tools/r8/utils/R8PartialCompilationConfiguration.java
+++ b/src/main/java/com/android/tools/r8/utils/R8PartialCompilationConfiguration.java
@@ -28,6 +28,10 @@
public Consumer<AndroidApp> r8OutputAppConsumer;
public Consumer<AndroidApp> d8OutputAppConsumer;
+ public Consumer<InternalOptions> d8DexOptionsConsumer = ConsumerUtils.emptyConsumer();
+ public Consumer<InternalOptions> d8MergeOptionsConsumer = ConsumerUtils.emptyConsumer();
+ public Consumer<InternalOptions> r8OptionsConsumer = ConsumerUtils.emptyConsumer();
+
private static final R8PartialCompilationConfiguration disabledConfiguration =
new R8PartialCompilationConfiguration(false, null, null);
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 7380554..1ea5acf 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
@@ -3,9 +3,14 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.benchmarks.appdumps;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+
import com.android.tools.r8.CompilationMode;
import com.android.tools.r8.LibraryDesugaringTestConfiguration;
import com.android.tools.r8.R8FullTestBuilder;
+import com.android.tools.r8.R8PartialTestBuilder;
+import com.android.tools.r8.R8TestBuilder;
import com.android.tools.r8.TestBase;
import com.android.tools.r8.TestBase.Backend;
import com.android.tools.r8.TestCompilerBuilder;
@@ -22,10 +27,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.errors.Unimplemented;
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 com.android.tools.r8.utils.AndroidApiLevel;
import com.google.common.collect.ImmutableSet;
import java.io.IOException;
import java.lang.annotation.RetentionPolicy;
@@ -139,6 +146,25 @@
.build();
}
+ public BenchmarkConfig buildR8WithPartialShrinking() {
+ verify();
+ return BenchmarkConfig.builder()
+ .setName(name)
+ .setTarget(BenchmarkTarget.R8)
+ .setSuite(BenchmarkSuite.OPENSOURCE_BENCHMARKS)
+ .setMethod(runR8WithPartialShrinking(this))
+ .setFromRevision(fromRevision)
+ .addDependency(dumpDependency)
+ .measureRunTime()
+ .measureCodeSize()
+ .measureInstructionCodeSize()
+ .measureComposableInstructionCodeSize()
+ .measureDexSegmentsCodeSize()
+ .measureDex2OatCodeSize()
+ .setTimeout(10, TimeUnit.MINUTES)
+ .build();
+ }
+
public BenchmarkConfig buildR8WithResourceShrinking() {
return buildR8WithResourceShrinking(getDefaultR8Configuration());
}
@@ -253,7 +279,20 @@
options -> options.getOpenClosedInterfacesOptions().suppressAllOpenInterfaces());
}
- private static ThrowableConsumer<? super R8FullTestBuilder>
+ private static ThrowableConsumer<? super R8PartialTestBuilder>
+ getDefaultR8PartialConfiguration() {
+ return testBuilder ->
+ testBuilder
+ .allowUnnecessaryDontWarnWildcards()
+ .allowUnusedDontWarnPatterns()
+ .allowUnusedProguardConfigurationRules()
+ // TODO(b/222228826): Disallow unrecognized diagnostics and open interfaces.
+ .allowDiagnosticMessages()
+ .addR8PartialOptionsModification(
+ options -> options.getOpenClosedInterfacesOptions().suppressAllOpenInterfaces());
+ }
+
+ private static ThrowableConsumer<? super R8TestBuilder<?, ?, ?>>
getKeepComposableAnnotationsConfiguration() {
return testBuilder ->
testBuilder
@@ -268,6 +307,10 @@
return internalRunR8(builder, false, configuration);
}
+ private static BenchmarkMethod runR8WithPartialShrinking(AppDumpBenchmarkBuilder builder) {
+ return internalRunR8Partial(builder, getDefaultR8PartialConfiguration());
+ }
+
private static BenchmarkMethod runR8WithResourceShrinking(
AppDumpBenchmarkBuilder builder, ThrowableConsumer<? super R8FullTestBuilder> configuration) {
return internalRunR8(builder, true, configuration);
@@ -331,6 +374,52 @@
});
}
+ private static BenchmarkMethod internalRunR8Partial(
+ AppDumpBenchmarkBuilder builder,
+ ThrowableConsumer<? super R8PartialTestBuilder> configuration) {
+ return environment ->
+ BenchmarkBase.runner(environment)
+ .setWarmupIterations(0)
+ .run(
+ results -> {
+ CompilerDump dump = builder.getExtractedDump(environment);
+ DumpOptions dumpProperties = dump.getBuildProperties();
+
+ // Verify that the dump does not use features that are not implemented below.
+ dump.forEachFeatureArchive(
+ feature -> {
+ throw new Unimplemented();
+ });
+ assertFalse(dumpProperties.getEnableSameFilePolicy());
+ assertFalse(dumpProperties.getIsolatedSplits());
+ assertNull(dumpProperties.getAndroidApiExtensionPackages());
+
+ // Run R8.
+ TestBase.testForR8Partial(environment.getTemp(), Backend.DEX)
+ .addProgramFiles(dump.getProgramArchive())
+ .addLibraryFiles(dump.getLibraryArchive())
+ .addKeepRuleFiles(dump.getProguardConfigFile())
+ // TODO(b/388452773): Fix support for default interface methods.
+ .setMinApi(Math.max(dumpProperties.getMinApi(), AndroidApiLevel.N.getLevel()))
+ .setR8PartialConfiguration(
+ b -> builder.programPackages.forEach(b::addJavaTypeIncludePattern))
+ .apply(b -> addDesugaredLibrary(b, dump))
+ .apply(configuration)
+ .applyIf(
+ environment.getConfig().containsComposableCodeSizeMetric(),
+ getKeepComposableAnnotationsConfiguration())
+ .apply(
+ r ->
+ r.benchmarkCompile(results)
+ .benchmarkCodeSize(results)
+ .benchmarkInstructionCodeSize(results)
+ .benchmarkDexSegmentsCodeSize(results)
+ .benchmarkDex2OatCodeSize(
+ results,
+ environment.getConfig().isDex2OatVerificationEnabled()));
+ });
+ }
+
private static BenchmarkMethod runBatchD8(AppDumpBenchmarkBuilder builder) {
assert builder.compilationMode != null;
return environment ->
diff --git a/src/test/java/com/android/tools/r8/benchmarks/appdumps/NowInAndroidBenchmarks.java b/src/test/java/com/android/tools/r8/benchmarks/appdumps/NowInAndroidBenchmarks.java
index e2fca85..9ed646a 100644
--- a/src/test/java/com/android/tools/r8/benchmarks/appdumps/NowInAndroidBenchmarks.java
+++ b/src/test/java/com/android/tools/r8/benchmarks/appdumps/NowInAndroidBenchmarks.java
@@ -80,6 +80,12 @@
.setFromRevision(16017)
.buildR8(),
AppDumpBenchmarkBuilder.builder()
+ .setName("NowInAndroidAppPartial")
+ .setDumpDependencyPath(dump)
+ .addProgramPackages("androidx.**", "kotlin.**", "kotlinx.**")
+ .setFromRevision(16017)
+ .buildR8WithPartialShrinking(),
+ AppDumpBenchmarkBuilder.builder()
.setName("NowInAndroidAppWithResourceShrinking")
.setDumpDependencyPath(dump)
.setFromRevision(16017)
diff --git a/src/test/testbase/java/com/android/tools/r8/R8PartialTestBuilder.java b/src/test/testbase/java/com/android/tools/r8/R8PartialTestBuilder.java
index 3dacb92..d3320d3 100644
--- a/src/test/testbase/java/com/android/tools/r8/R8PartialTestBuilder.java
+++ b/src/test/testbase/java/com/android/tools/r8/R8PartialTestBuilder.java
@@ -6,6 +6,7 @@
import com.android.tools.r8.R8Command.Builder;
import com.android.tools.r8.TestBase.Backend;
import com.android.tools.r8.benchmarks.BenchmarkResults;
+import com.android.tools.r8.errors.Unreachable;
import com.android.tools.r8.shaking.ProguardConfigurationRule;
import com.android.tools.r8.utils.AndroidApp;
import com.android.tools.r8.utils.Box;
@@ -38,10 +39,25 @@
@Override
public boolean isR8TestBuilder() {
+ return false;
+ }
+
+ @Override
+ public R8TestBuilder<?, ?, ?> asR8TestBuilder() {
+ return null;
+ }
+
+ @Override
+ public boolean isR8PartialTestBuilder() {
return true;
}
@Override
+ public R8PartialTestBuilder asR8PartialTestBuilder() {
+ return this;
+ }
+
+ @Override
R8PartialTestBuilder self() {
return this;
}
@@ -117,4 +133,57 @@
r8OutputAppBox.get(),
d8OutputAppBox.get());
}
+
+ @Override
+ public R8PartialTestBuilder addOptionsModification(Consumer<InternalOptions> optionsConsumer) {
+ throw new Unreachable(
+ "Unexpected use of R8PartialTestBuilder#addOptionsModification. "
+ + "Did you mean addD8PartialOptionsModification or addR8PartialOptionsModification?");
+ }
+
+ public R8PartialTestBuilder addD8PartialOptionsModification(Consumer<InternalOptions> consumer) {
+ return super.addOptionsModification(
+ options ->
+ options.partialCompilationConfiguration.d8DexOptionsConsumer =
+ options.partialCompilationConfiguration.d8DexOptionsConsumer.andThen(consumer));
+ }
+
+ public R8PartialTestBuilder addD8MergeOptionsModification(Consumer<InternalOptions> consumer) {
+ return super.addOptionsModification(
+ options ->
+ options.partialCompilationConfiguration.d8MergeOptionsConsumer =
+ options.partialCompilationConfiguration.d8MergeOptionsConsumer.andThen(consumer));
+ }
+
+ public R8PartialTestBuilder addR8PartialOptionsModification(Consumer<InternalOptions> consumer) {
+ return super.addOptionsModification(
+ options ->
+ options.partialCompilationConfiguration.r8OptionsConsumer =
+ options.partialCompilationConfiguration.r8OptionsConsumer.andThen(consumer));
+ }
+
+ public R8PartialTestBuilder addGlobalOptionsModification(Consumer<InternalOptions> consumer) {
+ return addD8PartialOptionsModification(consumer)
+ .addD8MergeOptionsModification(consumer)
+ .addR8PartialOptionsModification(consumer);
+ }
+
+ @Override
+ public R8PartialTestBuilder allowUnnecessaryDontWarnWildcards() {
+ return addR8PartialOptionsModification(
+ options -> options.getTestingOptions().allowUnnecessaryDontWarnWildcards = true);
+ }
+
+ @Override
+ public R8PartialTestBuilder allowUnusedDontWarnPatterns() {
+ return addR8PartialOptionsModification(
+ options -> options.getTestingOptions().allowUnusedDontWarnRules = true);
+ }
+
+ @Override
+ public R8PartialTestBuilder enableExperimentalKeepAnnotations() {
+ return addR8PartialOptionsModification(
+ o -> o.getTestingOptions().enableEmbeddedKeepAnnotations = true)
+ .addKeepAnnoLibToClasspath();
+ }
}
diff --git a/src/test/testbase/java/com/android/tools/r8/R8TestBuilder.java b/src/test/testbase/java/com/android/tools/r8/R8TestBuilder.java
index b5da273..3e294f0 100644
--- a/src/test/testbase/java/com/android/tools/r8/R8TestBuilder.java
+++ b/src/test/testbase/java/com/android/tools/r8/R8TestBuilder.java
@@ -445,7 +445,7 @@
return addOptionsModification(options -> options.testing.allowUnusedDontWarnRules = true);
}
- public T allowUnusedProguardConfigurationRules() {
+ public final T allowUnusedProguardConfigurationRules() {
return allowUnusedProguardConfigurationRules(true);
}
@@ -811,7 +811,11 @@
}
public T enableExperimentalKeepAnnotations() {
- addOptionsModification(o -> o.testing.enableEmbeddedKeepAnnotations = true);
+ return addOptionsModification(o -> o.testing.enableEmbeddedKeepAnnotations = true)
+ .addKeepAnnoLibToClasspath();
+ }
+
+ public T addKeepAnnoLibToClasspath() {
try {
builder.addClasspathFiles(KeepAnnoTestUtils.getKeepAnnoLib(getState().getTempFolder()));
return self();
diff --git a/src/test/testbase/java/com/android/tools/r8/TestCompilerBuilder.java b/src/test/testbase/java/com/android/tools/r8/TestCompilerBuilder.java
index f4f0034..ed19826 100644
--- a/src/test/testbase/java/com/android/tools/r8/TestCompilerBuilder.java
+++ b/src/test/testbase/java/com/android/tools/r8/TestCompilerBuilder.java
@@ -62,19 +62,26 @@
public static final Consumer<InternalOptions> DEFAULT_OPTIONS =
options -> {
options.testing.enableTestAssertions = true;
- options.testing.allowUnusedDontWarnRules = false;
- options.testing.allowUnnecessaryDontWarnWildcards = false;
- options.testing.listIterationRewritingEnabled = true;
- options.horizontalClassMergerOptions().enable();
- options.horizontalClassMergerOptions().setEnableInterfaceMerging();
- options.inlinerOptions().enableConstructorInliningWithFinalFields = true;
- options
- .getCfCodeAnalysisOptions()
- .setAllowUnreachableCfBlocks(false)
- .setEnableUnverifiableCodeReporting(true);
- options.getOpenClosedInterfacesOptions().disallowOpenInterfaces();
};
+ public static final Consumer<InternalOptions> DEFAULT_D8_OPTIONS = DEFAULT_OPTIONS;
+
+ public static final Consumer<InternalOptions> DEFAULT_R8_OPTIONS =
+ DEFAULT_OPTIONS.andThen(
+ options -> {
+ options.testing.allowUnusedDontWarnRules = false;
+ options.testing.allowUnnecessaryDontWarnWildcards = false;
+ options.testing.listIterationRewritingEnabled = true;
+ options.horizontalClassMergerOptions().enable();
+ options.horizontalClassMergerOptions().setEnableInterfaceMerging();
+ options.inlinerOptions().enableConstructorInliningWithFinalFields = true;
+ options
+ .getCfCodeAnalysisOptions()
+ .setAllowUnreachableCfBlocks(false)
+ .setEnableUnverifiableCodeReporting(true);
+ options.getOpenClosedInterfacesOptions().disallowOpenInterfaces();
+ });
+
final Backend backend;
// Default initialized setup. Can be overwritten if needed.
@@ -89,7 +96,7 @@
private boolean noMinApiLevel = false;
private int minApiLevel = -1;
private boolean optimizeMultidexForLinearAlloc = false;
- private Consumer<InternalOptions> optionsConsumer = DEFAULT_OPTIONS;
+ private Consumer<InternalOptions> optionsConsumer;
private ByteArrayOutputStream stdout = null;
private boolean stdOutForwarding = true;
private PrintStream oldStdout = null;
@@ -124,6 +131,14 @@
return null;
}
+ public boolean isR8PartialTestBuilder() {
+ return false;
+ }
+
+ public R8PartialTestBuilder asR8PartialTestBuilder() {
+ return null;
+ }
+
public boolean isTestShrinkerBuilder() {
return false;
}
@@ -152,6 +167,21 @@
assert backend == Backend.CF;
setOutputMode(OutputMode.ClassFile);
}
+ if (isD8TestBuilder()) {
+ optionsConsumer = DEFAULT_D8_OPTIONS;
+ } else if (isR8TestBuilder()) {
+ optionsConsumer = DEFAULT_R8_OPTIONS;
+ } else if (isR8PartialTestBuilder()) {
+ optionsConsumer =
+ DEFAULT_OPTIONS.andThen(
+ options -> {
+ options.partialCompilationConfiguration.d8DexOptionsConsumer = DEFAULT_D8_OPTIONS;
+ options.partialCompilationConfiguration.d8MergeOptionsConsumer = DEFAULT_D8_OPTIONS;
+ options.partialCompilationConfiguration.r8OptionsConsumer = DEFAULT_R8_OPTIONS;
+ });
+ } else {
+ optionsConsumer = DEFAULT_OPTIONS;
+ }
}
protected int getMinApiLevel() {
@@ -298,7 +328,7 @@
}
if (!noMinApiLevel
&& backend.isDex()
- && (isD8TestBuilder() || isR8TestBuilder())
+ && (isD8TestBuilder() || isR8TestBuilder() || isR8PartialTestBuilder())
&& !isBenchmarkRunner) {
int minApiLevel = builder.getMinApiLevel();
Consumer<InternalOptions> previousConsumer = optionsConsumer;
@@ -327,6 +357,12 @@
if (isD8TestBuilder() || isR8TestBuilder()) {
addOptionsModification(
o -> o.getArtProfileOptions().setEnableCompletenessCheckForTesting(!isBenchmarkRunner));
+ } else if (isR8PartialTestBuilder()) {
+ asR8PartialTestBuilder()
+ .addGlobalOptionsModification(
+ o ->
+ o.getArtProfileOptions()
+ .setEnableCompletenessCheckForTesting(!isBenchmarkRunner));
}
builder.setOptimizeMultidexForLinearAlloc(optimizeMultidexForLinearAlloc);
diff --git a/tools/perf.py b/tools/perf.py
index 577647d..9bf5803 100755
--- a/tools/perf.py
+++ b/tools/perf.py
@@ -74,6 +74,9 @@
'NowInAndroidAppNoJ$Release': {
'targets': ['d8']
},
+ 'NowInAndroidAppPartial': {
+ 'targets': ['r8-full']
+ },
'OwlApp': {
'targets': ['r8-full']
},