blob: bc979e923065862803ba0ab9bdbc1a982aca8b17 [file]
// Copyright (c) 2026, the R8 project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.benchmarks.appdumps;
import com.android.tools.r8.R8FullTestBuilder;
import com.android.tools.r8.R8PartialTestBuilder;
import com.android.tools.r8.TestDeps;
import com.android.tools.r8.TestParameters;
import com.android.tools.r8.benchmarks.BenchmarkBase;
import com.android.tools.r8.benchmarks.BenchmarkConfig;
import com.google.common.collect.ImmutableList;
import java.nio.file.Path;
import java.util.List;
import java.util.function.Supplier;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
@RunWith(Parameterized.class)
public abstract class OpenSourceBenchmarks extends BenchmarkBase {
protected OpenSourceBenchmarks(BenchmarkConfig config, TestParameters parameters) {
super(config, parameters);
}
public static List<BenchmarkConfig> configs() {
return ImmutableList.of(
FeederApp.config(),
FeederAppPartial.config(),
BookStoryApp.config(),
BookStoryAppPartial.config(),
ReadYouApp.config(),
ReadYouAppPartial.config(),
FossifyFileManagerApp.config(),
FossifyFileManagerAppPartial.config(),
NewPipeKotlinApp.config(),
NewPipeKotlinAppPartial.config(),
TuskyApp.config(),
TuskyAppPartial.config(),
KeePassDXApp.config(),
KeePassDXAppPartial.config(),
OmniNotesApp.config(),
OmniNotesAppPartial.config(),
OpenTracksApp.config(),
OpenTracksAppPartial.config());
}
private static void configureWithoutOpenInterfaceSuppression(R8FullTestBuilder testBuilder) {
testBuilder
.addDontWarn("*")
.allowDiagnosticMessages()
.allowUnnecessaryDontWarnWildcards()
.allowUnusedDontWarnPatterns()
.allowUnusedProguardConfigurationRules()
.addOptionsModification(
options -> options.getCfCodeAnalysisOptions().setAllowUnreachableCfBlocks(true));
}
private static void configure(R8FullTestBuilder testBuilder) {
configureWithoutOpenInterfaceSuppression(testBuilder);
testBuilder.addOptionsModification(
options -> options.getOpenClosedInterfacesOptions().suppressAllOpenInterfaces());
}
private static void configureMinApi24WithoutOpenInterfaceSuppression(
R8FullTestBuilder testBuilder) {
configureWithoutOpenInterfaceSuppression(testBuilder);
// TODO(b/480100735): Remove once we have figured out how to deal with keepanno.
testBuilder.setMinApi(24);
}
private static void configureMinApi24(R8FullTestBuilder testBuilder) {
configure(testBuilder);
// TODO(b/480100735): Remove once we have figured out how to deal with keepanno.
testBuilder.setMinApi(24);
}
private static void configurePartialWithoutOpenInterfaceSuppression(
R8PartialTestBuilder testBuilder) {
testBuilder
.addDontWarn("*")
.allowDiagnosticMessages()
.allowUnnecessaryDontWarnWildcards()
.allowUnusedDontWarnPatterns()
.allowUnusedProguardConfigurationRules()
.addR8PartialR8OptionsModification(
options -> options.getCfCodeAnalysisOptions().setAllowUnreachableCfBlocks(true));
}
private static void configurePartial(R8PartialTestBuilder testBuilder) {
configurePartialWithoutOpenInterfaceSuppression(testBuilder);
testBuilder.addR8PartialR8OptionsModification(
options -> options.getOpenClosedInterfacesOptions().suppressAllOpenInterfaces());
}
private static void configureMinApi24PartialWithoutOpenInterfaceSuppression(
R8PartialTestBuilder testBuilder) {
configurePartialWithoutOpenInterfaceSuppression(testBuilder);
// TODO(b/480100735): Remove once we have figured out how to deal with keepanno.
testBuilder.setMinApi(24);
}
private static void configureMinApi24Partial(R8PartialTestBuilder testBuilder) {
configurePartial(testBuilder);
// TODO(b/480100735): Remove once we have figured out how to deal with keepanno.
testBuilder.setMinApi(24);
}
protected static AppDumpBenchmarkBuilder builder(String name, Supplier<Path> app) {
return AppDumpBenchmarkBuilder.builder()
.setName(name)
.setEnableResourceShrinking(true)
.setDumpDependencyPath(app)
.setFromRevision(16457);
}
public static class FeederApp extends OpenSourceBenchmarks {
@Parameters(name = "{0}")
public static List<Object[]> data() {
return parametersFromConfig(config());
}
public static BenchmarkConfig config() {
return builder("FeederApp", TestDeps::getFeederDir).buildR8(OpenSourceBenchmarks::configure);
}
public FeederApp(BenchmarkConfig config, TestParameters parameters) {
super(config, parameters);
}
}
public static class FeederAppPartial extends OpenSourceBenchmarks {
@Parameters(name = "{0}")
public static List<Object[]> data() {
return parametersFromConfig(config());
}
public static BenchmarkConfig config() {
return builder("FeederAppPartial", TestDeps::getFeederDir)
.buildR8WithPartialShrinking(OpenSourceBenchmarks::configurePartial);
}
public FeederAppPartial(BenchmarkConfig config, TestParameters parameters) {
super(config, parameters);
}
}
public static class BookStoryApp extends OpenSourceBenchmarks {
@Parameters(name = "{0}")
public static List<Object[]> data() {
return parametersFromConfig(config());
}
public static BenchmarkConfig config() {
return builder("BookStoryApp", TestDeps::getBookStoryDir)
.buildR8(OpenSourceBenchmarks::configure);
}
public BookStoryApp(BenchmarkConfig config, TestParameters parameters) {
super(config, parameters);
}
}
public static class BookStoryAppPartial extends OpenSourceBenchmarks {
@Parameters(name = "{0}")
public static List<Object[]> data() {
return parametersFromConfig(config());
}
public static BenchmarkConfig config() {
return builder("BookStoryAppPartial", TestDeps::getBookStoryDir)
.buildR8WithPartialShrinking(OpenSourceBenchmarks::configurePartial);
}
public BookStoryAppPartial(BenchmarkConfig config, TestParameters parameters) {
super(config, parameters);
}
}
public static class ReadYouApp extends OpenSourceBenchmarks {
@Parameters(name = "{0}")
public static List<Object[]> data() {
return parametersFromConfig(config());
}
public static BenchmarkConfig config() {
return builder("ReadYouApp", TestDeps::getReadYouDir)
.setRemoveDontObfuscate()
.buildR8(OpenSourceBenchmarks::configure);
}
public ReadYouApp(BenchmarkConfig config, TestParameters parameters) {
super(config, parameters);
}
}
public static class ReadYouAppPartial extends OpenSourceBenchmarks {
@Parameters(name = "{0}")
public static List<Object[]> data() {
return parametersFromConfig(config());
}
public static BenchmarkConfig config() {
return builder("ReadYouAppPartial", TestDeps::getReadYouDir)
.setRemoveDontObfuscate()
.buildR8WithPartialShrinking(OpenSourceBenchmarks::configurePartial);
}
public ReadYouAppPartial(BenchmarkConfig config, TestParameters parameters) {
super(config, parameters);
}
}
public static class FossifyFileManagerApp extends OpenSourceBenchmarks {
@Parameters(name = "{0}")
public static List<Object[]> data() {
return parametersFromConfig(config());
}
public static BenchmarkConfig config() {
return builder("FossifyFileManagerApp", TestDeps::getFossifyFileManagerDir)
// The host dex2oat boot image has no framework classes, so android.* types are
// unresolved. Glide's DrawableCrossFadeTransition.transition merges Drawable and
// ColorDrawable, which the verifier then rejects as a hard failure when the merge is
// used as a Drawable. On device the framework classes resolve and the method verifies.
.setEnableDex2OatVerification(false)
.buildR8(OpenSourceBenchmarks::configure);
}
public FossifyFileManagerApp(BenchmarkConfig config, TestParameters parameters) {
super(config, parameters);
}
}
public static class FossifyFileManagerAppPartial extends OpenSourceBenchmarks {
@Parameters(name = "{0}")
public static List<Object[]> data() {
return parametersFromConfig(config());
}
public static BenchmarkConfig config() {
return builder("FossifyFileManagerAppPartial", TestDeps::getFossifyFileManagerDir)
// The host dex2oat boot image has no framework classes, so android.* types are
// unresolved. Glide's DrawableCrossFadeTransition.transition merges Drawable and
// ColorDrawable, which the verifier then rejects as a hard failure when the merge is
// used as a Drawable. On device the framework classes resolve and the method verifies.
.setEnableDex2OatVerification(false)
.buildR8WithPartialShrinking(OpenSourceBenchmarks::configurePartial);
}
public FossifyFileManagerAppPartial(BenchmarkConfig config, TestParameters parameters) {
super(config, parameters);
}
}
public static class NewPipeKotlinApp extends OpenSourceBenchmarks {
@Parameters(name = "{0}")
public static List<Object[]> data() {
return parametersFromConfig(config());
}
public static BenchmarkConfig config() {
return builder("NewPipeKotlinApp", TestDeps::getNewPipeDir)
.setRemoveDontObfuscate()
.buildR8(OpenSourceBenchmarks::configureMinApi24);
}
public NewPipeKotlinApp(BenchmarkConfig config, TestParameters parameters) {
super(config, parameters);
}
}
public static class NewPipeKotlinAppPartial extends OpenSourceBenchmarks {
@Parameters(name = "{0}")
public static List<Object[]> data() {
return parametersFromConfig(config());
}
public static BenchmarkConfig config() {
return builder("NewPipeKotlinAppPartial", TestDeps::getNewPipeDir)
.setRemoveDontObfuscate()
.buildR8WithPartialShrinking(OpenSourceBenchmarks::configureMinApi24Partial);
}
public NewPipeKotlinAppPartial(BenchmarkConfig config, TestParameters parameters) {
super(config, parameters);
}
}
public static class TuskyApp extends OpenSourceBenchmarks {
@Parameters(name = "{0}")
public static List<Object[]> data() {
return parametersFromConfig(config());
}
public static BenchmarkConfig config() {
return builder("TuskyApp", TestDeps::getTuskyDir)
.buildR8(OpenSourceBenchmarks::configureWithoutOpenInterfaceSuppression);
}
public TuskyApp(BenchmarkConfig config, TestParameters parameters) {
super(config, parameters);
}
}
public static class TuskyAppPartial extends OpenSourceBenchmarks {
@Parameters(name = "{0}")
public static List<Object[]> data() {
return parametersFromConfig(config());
}
public static BenchmarkConfig config() {
return builder("TuskyAppPartial", TestDeps::getTuskyDir)
.buildR8WithPartialShrinking(
OpenSourceBenchmarks::configurePartialWithoutOpenInterfaceSuppression);
}
public TuskyAppPartial(BenchmarkConfig config, TestParameters parameters) {
super(config, parameters);
}
}
public static class KeePassDXApp extends OpenSourceBenchmarks {
@Parameters(name = "{0}")
public static List<Object[]> data() {
return parametersFromConfig(config());
}
public static BenchmarkConfig config() {
return builder("KeePassDXApp", TestDeps::getKeePassDXDir)
.setRemoveDontOptimize()
.buildR8(OpenSourceBenchmarks::configureMinApi24WithoutOpenInterfaceSuppression);
}
public KeePassDXApp(BenchmarkConfig config, TestParameters parameters) {
super(config, parameters);
}
}
public static class KeePassDXAppPartial extends OpenSourceBenchmarks {
@Parameters(name = "{0}")
public static List<Object[]> data() {
return parametersFromConfig(config());
}
public static BenchmarkConfig config() {
return builder("KeePassDXAppPartial", TestDeps::getKeePassDXDir)
.setRemoveDontOptimize()
.buildR8WithPartialShrinking(
OpenSourceBenchmarks::configureMinApi24PartialWithoutOpenInterfaceSuppression);
}
public KeePassDXAppPartial(BenchmarkConfig config, TestParameters parameters) {
super(config, parameters);
}
}
public static class OmniNotesApp extends OpenSourceBenchmarks {
@Parameters(name = "{0}")
public static List<Object[]> data() {
return parametersFromConfig(config());
}
public static BenchmarkConfig config() {
return builder("OmniNotesApp", TestDeps::getOmniNotesDir)
.setRemoveDontOptimize()
.setRemoveDontObfuscate()
// The host dex2oat boot image has no framework classes, so android.* types are
// unresolved. Glide's DrawableCrossFadeTransition.transition merges Drawable and
// ColorDrawable, which the verifier then rejects as a hard failure when the merge is
// used as a Drawable. On device the framework classes resolve and the method verifies.
.setEnableDex2OatVerification(false)
.buildR8(OpenSourceBenchmarks::configureWithoutOpenInterfaceSuppression);
}
public OmniNotesApp(BenchmarkConfig config, TestParameters parameters) {
super(config, parameters);
}
}
public static class OmniNotesAppPartial extends OpenSourceBenchmarks {
@Parameters(name = "{0}")
public static List<Object[]> data() {
return parametersFromConfig(config());
}
public static BenchmarkConfig config() {
return builder("OmniNotesAppPartial", TestDeps::getOmniNotesDir)
.setRemoveDontOptimize()
.setRemoveDontObfuscate()
// The host dex2oat boot image has no framework classes, so android.* types are
// unresolved. Glide's DrawableCrossFadeTransition.transition merges Drawable and
// ColorDrawable, which the verifier then rejects as a hard failure when the merge is
// used as a Drawable. On device the framework classes resolve and the method verifies.
.setEnableDex2OatVerification(false)
.buildR8WithPartialShrinking(
OpenSourceBenchmarks::configurePartialWithoutOpenInterfaceSuppression);
}
public OmniNotesAppPartial(BenchmarkConfig config, TestParameters parameters) {
super(config, parameters);
}
}
public static class OpenTracksApp extends OpenSourceBenchmarks {
@Parameters(name = "{0}")
public static List<Object[]> data() {
return parametersFromConfig(config());
}
public static BenchmarkConfig config() {
return builder("OpenTracksApp", TestDeps::getOpenTracksDir)
.setRemoveDontOptimize()
.buildR8(OpenSourceBenchmarks::configureWithoutOpenInterfaceSuppression);
}
public OpenTracksApp(BenchmarkConfig config, TestParameters parameters) {
super(config, parameters);
}
}
public static class OpenTracksAppPartial extends OpenSourceBenchmarks {
@Parameters(name = "{0}")
public static List<Object[]> data() {
return parametersFromConfig(config());
}
public static BenchmarkConfig config() {
return builder("OpenTracksAppPartial", TestDeps::getOpenTracksDir)
.setRemoveDontOptimize()
.buildR8WithPartialShrinking(
OpenSourceBenchmarks::configurePartialWithoutOpenInterfaceSuppression);
}
public OpenTracksAppPartial(BenchmarkConfig config, TestParameters parameters) {
super(config, parameters);
}
}
}