Support for writing benchmark result to json and overriding iterations
Change-Id: I2dc1482a36d3479f0fba7ee65ef850a93e1b9b83
diff --git a/src/test/java/com/android/tools/r8/benchmarks/BenchmarkBase.java b/src/test/java/com/android/tools/r8/benchmarks/BenchmarkBase.java
index 1cb50ba..917c268 100644
--- a/src/test/java/com/android/tools/r8/benchmarks/BenchmarkBase.java
+++ b/src/test/java/com/android/tools/r8/benchmarks/BenchmarkBase.java
@@ -40,7 +40,7 @@
config.run(new BenchmarkEnvironment(config, temp, false));
}
- public static BenchmarkRunner runner(BenchmarkConfig config) {
- return BenchmarkRunner.runner(config);
+ public static BenchmarkRunner runner(BenchmarkEnvironment environment) {
+ return BenchmarkRunner.runner(environment);
}
}
diff --git a/src/test/java/com/android/tools/r8/benchmarks/BenchmarkEnvironment.java b/src/test/java/com/android/tools/r8/benchmarks/BenchmarkEnvironment.java
index fe36c52..267ecc1 100644
--- a/src/test/java/com/android/tools/r8/benchmarks/BenchmarkEnvironment.java
+++ b/src/test/java/com/android/tools/r8/benchmarks/BenchmarkEnvironment.java
@@ -36,4 +36,20 @@
public Path getGolemDependencyRoot() {
return Paths.get("benchmarks", config.getDependencyDirectoryName());
}
+
+ public boolean hasBenchmarkIterationsOverride() {
+ return System.getProperty("BENCHMARK_ITERATIONS") != null;
+ }
+
+ public int getBenchmarkIterationsOverride() {
+ return Integer.parseInt(System.getProperty("BENCHMARK_ITERATIONS"));
+ }
+
+ public boolean hasOutputPath() {
+ return System.getProperty("BENCHMARK_OUTPUT") != null;
+ }
+
+ public Path getOutputPath() {
+ return Paths.get(System.getProperty("BENCHMARK_OUTPUT"));
+ }
}
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 14b10f4..702374b 100644
--- a/src/test/java/com/android/tools/r8/benchmarks/BenchmarkResultsCollection.java
+++ b/src/test/java/com/android/tools/r8/benchmarks/BenchmarkResultsCollection.java
@@ -3,6 +3,8 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.benchmarks;
+import com.android.tools.r8.errors.Unimplemented;
+import java.io.PrintStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -54,4 +56,9 @@
singleResults.printResults(mode);
}
}
+
+ @Override
+ public void writeResults(PrintStream out) {
+ throw new Unimplemented();
+ }
}
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 e0bb9f193..d44f1c0 100644
--- a/src/test/java/com/android/tools/r8/benchmarks/BenchmarkResultsSingle.java
+++ b/src/test/java/com/android/tools/r8/benchmarks/BenchmarkResultsSingle.java
@@ -3,8 +3,11 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.benchmarks;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
import it.unimi.dsi.fastutil.longs.LongArrayList;
import it.unimi.dsi.fastutil.longs.LongList;
+import java.io.PrintStream;
import java.util.Set;
public class BenchmarkResultsSingle implements BenchmarkResults {
@@ -19,6 +22,18 @@
this.metrics = metrics;
}
+ public String getName() {
+ return name;
+ }
+
+ public LongList getCodeSizeResults() {
+ return codeSizeResults;
+ }
+
+ public LongList getRuntimeResults() {
+ return runtimeResults;
+ }
+
@Override
public void addRuntimeResult(long result) {
verifyMetric(BenchmarkMetric.RunTimeRaw, metrics.contains(BenchmarkMetric.RunTimeRaw), true);
@@ -93,4 +108,13 @@
printCodeSize(size);
}
}
+
+ @Override
+ public void writeResults(PrintStream out) {
+ Gson gson =
+ new GsonBuilder()
+ .registerTypeAdapter(BenchmarkResultsSingle.class, new BenchmarkResultsSingleAdapter())
+ .create();
+ out.print(gson.toJson(this));
+ }
}
diff --git a/src/test/java/com/android/tools/r8/benchmarks/BenchmarkResultsSingleAdapter.java b/src/test/java/com/android/tools/r8/benchmarks/BenchmarkResultsSingleAdapter.java
new file mode 100644
index 0000000..55936d7
--- /dev/null
+++ b/src/test/java/com/android/tools/r8/benchmarks/BenchmarkResultsSingleAdapter.java
@@ -0,0 +1,34 @@
+// Copyright (c) 2024, 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;
+
+import com.android.tools.r8.utils.ListUtils;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonElement;
+import com.google.gson.JsonObject;
+import com.google.gson.JsonSerializationContext;
+import com.google.gson.JsonSerializer;
+import java.lang.reflect.Type;
+
+public class BenchmarkResultsSingleAdapter implements JsonSerializer<BenchmarkResultsSingle> {
+
+ @Override
+ public JsonElement serialize(
+ BenchmarkResultsSingle result, Type type, JsonSerializationContext jsonSerializationContext) {
+ JsonArray resultsArray = new JsonArray();
+ ListUtils.forEachWithIndex(
+ result.getCodeSizeResults(),
+ (codeSizeResult, iteration) -> {
+ JsonObject resultObject = new JsonObject();
+ resultObject.addProperty("code_size", codeSizeResult);
+ resultObject.addProperty("runtime", result.getRuntimeResults().getLong(iteration));
+ resultsArray.add(resultObject);
+ });
+
+ JsonObject benchmarkObject = new JsonObject();
+ benchmarkObject.addProperty("benchmark_name", result.getName());
+ benchmarkObject.add("results", resultsArray);
+ return benchmarkObject;
+ }
+}
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 2ac97a6..c7319f7 100644
--- a/src/test/java/com/android/tools/r8/benchmarks/BenchmarkResultsWarmup.java
+++ b/src/test/java/com/android/tools/r8/benchmarks/BenchmarkResultsWarmup.java
@@ -3,8 +3,10 @@
// BSD-style license that can be found in the LICENSE file.
package com.android.tools.r8.benchmarks;
+import com.android.tools.r8.errors.Unimplemented;
import it.unimi.dsi.fastutil.longs.LongArrayList;
import it.unimi.dsi.fastutil.longs.LongList;
+import java.io.PrintStream;
public class BenchmarkResultsWarmup implements BenchmarkResults {
@@ -61,4 +63,9 @@
BenchmarkResults.prettyMetric(
name, BenchmarkMetric.StartupTime, BenchmarkResults.prettyTime(result)));
}
+
+ @Override
+ public void writeResults(PrintStream out) {
+ throw new Unimplemented();
+ }
}
diff --git a/src/test/java/com/android/tools/r8/benchmarks/BenchmarkRunner.java b/src/test/java/com/android/tools/r8/benchmarks/BenchmarkRunner.java
index 2fed6dc..72d7adc 100644
--- a/src/test/java/com/android/tools/r8/benchmarks/BenchmarkRunner.java
+++ b/src/test/java/com/android/tools/r8/benchmarks/BenchmarkRunner.java
@@ -4,6 +4,9 @@
package com.android.tools.r8.benchmarks;
import com.android.tools.r8.benchmarks.BenchmarkResults.ResultMode;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.nio.file.Files;
public class BenchmarkRunner {
@@ -11,17 +14,17 @@
void run(BenchmarkResults results) throws Exception;
}
- private final BenchmarkConfig config;
+ private final BenchmarkEnvironment environment;
private int warmups = 0;
private int iterations = 1;
private ResultMode resultMode = BenchmarkResults.ResultMode.AVERAGE;
- private BenchmarkRunner(BenchmarkConfig config) {
- this.config = config;
+ private BenchmarkRunner(BenchmarkEnvironment environment) {
+ this.environment = environment;
}
- public static BenchmarkRunner runner(BenchmarkConfig config) {
- return new BenchmarkRunner(config);
+ public static BenchmarkRunner runner(BenchmarkEnvironment environment) {
+ return new BenchmarkRunner(environment);
}
public BenchmarkRunner setWarmupIterations(int iterations) {
@@ -29,6 +32,12 @@
return this;
}
+ public int getBenchmarkIterations() {
+ return environment.hasBenchmarkIterationsOverride()
+ ? environment.getBenchmarkIterationsOverride()
+ : iterations;
+ }
+
public BenchmarkRunner setBenchmarkIterations(int iterations) {
this.iterations = iterations;
return this;
@@ -46,6 +55,7 @@
public void run(BenchmarkRunnerFunction fn) throws Exception {
long warmupTotalTime = 0;
+ BenchmarkConfig config = environment.getConfig();
BenchmarkResults warmupResults = new BenchmarkResultsWarmup(config.getName());
if (warmups > 0) {
long start = System.nanoTime();
@@ -59,7 +69,7 @@
? new BenchmarkResultsSingle(config.getName(), config.getMetrics())
: new BenchmarkResultsCollection(config.getSubBenchmarks());
long start = System.nanoTime();
- for (int i = 0; i < iterations; i++) {
+ for (int i = 0; i < getBenchmarkIterations(); i++) {
fn.run(results);
}
long benchmarkTotalTime = System.nanoTime() - start;
@@ -74,8 +84,11 @@
warmupResults.printResults(resultMode);
}
}
- printMetaInfo("benchmark", iterations, benchmarkTotalTime);
+ printMetaInfo("benchmark", getBenchmarkIterations(), benchmarkTotalTime);
results.printResults(resultMode);
+ if (environment.hasOutputPath()) {
+ writeResults(results);
+ }
System.out.println();
}
@@ -84,4 +97,11 @@
System.out.println(" " + kind + " iterations: " + iterations);
System.out.println(" " + kind + " total time: " + BenchmarkResults.prettyTime(totalTime));
}
+
+ private void writeResults(BenchmarkResults results) throws IOException {
+ try (PrintStream printStream =
+ new PrintStream(Files.newOutputStream(environment.getOutputPath()))) {
+ results.writeResults(printStream);
+ }
+ }
}
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 7e2a677..ac4f229 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
@@ -203,7 +203,7 @@
private static BenchmarkMethod internalRunR8(
AppDumpBenchmarkBuilder builder, boolean enableResourceShrinking) {
return environment ->
- BenchmarkBase.runner(environment.getConfig())
+ BenchmarkBase.runner(environment)
.setWarmupIterations(1)
.run(
results -> {
@@ -244,7 +244,7 @@
private static BenchmarkMethod runBatchD8(AppDumpBenchmarkBuilder builder) {
return environment ->
- BenchmarkBase.runner(environment.getConfig())
+ BenchmarkBase.runner(environment)
.setWarmupIterations(1)
.run(
results -> {
@@ -262,7 +262,7 @@
private static BenchmarkMethod runIncrementalD8(AppDumpBenchmarkBuilder builder) {
return environment ->
- BenchmarkBase.runner(environment.getConfig())
+ BenchmarkBase.runner(environment)
.setWarmupIterations(1)
.reportResultSum()
.run(
diff --git a/src/test/java/com/android/tools/r8/benchmarks/desugaredlib/L8Benchmark.java b/src/test/java/com/android/tools/r8/benchmarks/desugaredlib/L8Benchmark.java
index 3f12fc8..adfa5f8 100644
--- a/src/test/java/com/android/tools/r8/benchmarks/desugaredlib/L8Benchmark.java
+++ b/src/test/java/com/android/tools/r8/benchmarks/desugaredlib/L8Benchmark.java
@@ -65,7 +65,7 @@
ImmutableSet.of(ANDROID_JAR.getRoot(environment).resolve("android.jar")),
LibraryDesugaringSpecification.JDK11_DESCRIPTOR,
"");
- runner(environment.getConfig())
+ runner(environment)
.setWarmupIterations(1)
.setBenchmarkIterations(10)
.reportResultSum()
diff --git a/src/test/java/com/android/tools/r8/benchmarks/desugaredlib/LegacyDesugaredLibraryBenchmark.java b/src/test/java/com/android/tools/r8/benchmarks/desugaredlib/LegacyDesugaredLibraryBenchmark.java
index 6b5e4f9..2d50a3d 100644
--- a/src/test/java/com/android/tools/r8/benchmarks/desugaredlib/LegacyDesugaredLibraryBenchmark.java
+++ b/src/test/java/com/android/tools/r8/benchmarks/desugaredlib/LegacyDesugaredLibraryBenchmark.java
@@ -54,7 +54,7 @@
}
public static void run(BenchmarkEnvironment environment) throws Exception {
- runner(environment.getConfig())
+ runner(environment)
.setWarmupIterations(1)
.setBenchmarkIterations(10)
.reportResultSum()
diff --git a/src/test/java/com/android/tools/r8/benchmarks/helloworld/HelloWorldBenchmark.java b/src/test/java/com/android/tools/r8/benchmarks/helloworld/HelloWorldBenchmark.java
index cb43a1d..4c8c31c 100644
--- a/src/test/java/com/android/tools/r8/benchmarks/helloworld/HelloWorldBenchmark.java
+++ b/src/test/java/com/android/tools/r8/benchmarks/helloworld/HelloWorldBenchmark.java
@@ -101,7 +101,7 @@
public static BenchmarkMethod benchmarkD8(Options options) {
return environment ->
- runner(environment.getConfig())
+ runner(environment)
.setWarmupIterations(1)
.setBenchmarkIterations(100)
.reportResultSum()
@@ -119,7 +119,7 @@
public static BenchmarkMethod benchmarkR8(Options options) {
return environment ->
- runner(environment.getConfig())
+ runner(environment)
.setWarmupIterations(1)
.setBenchmarkIterations(4)
.reportResultSum()
diff --git a/src/test/java/com/android/tools/r8/benchmarks/retrace/RetraceStackTraceBenchmark.java b/src/test/java/com/android/tools/r8/benchmarks/retrace/RetraceStackTraceBenchmark.java
index 28e1e83..c3cd9d0 100644
--- a/src/test/java/com/android/tools/r8/benchmarks/retrace/RetraceStackTraceBenchmark.java
+++ b/src/test/java/com/android/tools/r8/benchmarks/retrace/RetraceStackTraceBenchmark.java
@@ -59,7 +59,7 @@
public static BenchmarkMethod benchmarkRetrace() {
return environment ->
- runner(environment.getConfig())
+ runner(environment)
.setWarmupIterations(1)
.setBenchmarkIterations(4)
.reportResultSum()
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 3e52ba7..e19cd88 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
@@ -4,6 +4,7 @@
package com.android.tools.r8.benchmarks;
import com.android.tools.r8.utils.StringUtils;
+import java.io.PrintStream;
public interface BenchmarkResults {
// Append a runtime result. This may be summed or averaged depending on the benchmark set up.
@@ -21,6 +22,8 @@
void printResults(ResultMode resultMode);
+ void writeResults(PrintStream out);
+
static String prettyTime(long nanoTime) {
return "" + (nanoTime / 1000000) + " ms";
}
diff --git a/tools/run_benchmark.py b/tools/run_benchmark.py
index 3962d59..8948df7 100755
--- a/tools/run_benchmark.py
+++ b/tools/run_benchmark.py
@@ -63,6 +63,12 @@
help='Enable assertions when running',
default=False,
action='store_true')
+ result.add_argument('--iterations',
+ '-i',
+ help='Number of iterations to run',
+ type=int)
+ result.add_argument('--output',
+ help='Output path where to write the result')
result.add_argument('--print-times',
help='Print timing information from r8',
default=False,
@@ -81,8 +87,12 @@
def main(argv, temp):
(options, args) = parse_options(argv)
+ if options.output:
+ options.output = os.path.abspath(options.output)
+
if options.temp:
temp = options.temp
+ os.makedirs(temp, exist_ok=True)
if options.golem:
options.no_build = True
@@ -139,6 +149,10 @@
f'-DTEST_DATA_LOCATION={utils.REPO_ROOT}/d8_r8/test_modules/tests_java_8/build/classes/java/test',
f'-DTESTBASE_DATA_LOCATION={utils.REPO_ROOT}/d8_r8/test_modules/testbase/build/classes/java/main',
])
+ if options.iterations:
+ cmd.append(f'-DBENCHMARK_ITERATIONS={options.iterations}')
+ if options.output:
+ cmd.append(f'-DBENCHMARK_OUTPUT={options.output}')
cmd.extend(['-cp', ':'.join([r8jar] + testjars)])
cmd.extend([
'com.android.tools.r8.benchmarks.BenchmarkMainEntryRunner',