blob: 7ed223f9739c9360e1744f0000d4cfaa61f829b2 [file] [log] [blame]
// Copyright (c) 2018, 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.sample.split;
import android.app.Activity;
import android.os.Bundle;
import com.android.tools.r8.sample.split.R;
import com.android.tools.r8.sample.split.SplitClass;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Multiset;
import com.google.common.collect.ConcurrentHashMultiset;
import java.util.ArrayList;
import java.util.List;
/**
* Benchmarking of splits. Generally the naming is like this:
* Base -> Split (no postfix)
* Base -> Base (Local, to get the corresponding performance if no split involved)
* Split -> Split (SplitLocal)
* Split -> Base (SplitCallback)
* Base no call overhead (Baseline)
* In most of these cases we have the methods duplicated between the SplitClass and this class.
* This is to enable output of the split and not split version of the code without having to
* run in two different build configurations (i.e., with and without using split code)
*/
public class R8Activity extends Activity {
// Enables easy splitting of iterations to better see effect of jit in later versions of art
public static final int ITERATIONS = 100000;
public static final int SPLITS = 1;
private int res = 0;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setTheme(android.R.style.Theme_Light);
setContentView(R.layout.main);
long total = 0;
for (int i = 0; i < SPLITS; i++) {
total += benchmarkCallBaseline();
}
System.out.println("CallBaseline Total: " + total);
total = 0;
for (int i = 0; i < SPLITS; i++) {
total += benchmarkCall();
}
System.out.println("Call Total: " + total);
total = 0;
for (int i = 0; i < SPLITS; i++) {
total += benchmarkCallSplitLocal();
}
System.out.println("CallSplitLocal Total: " + total);
total = 0;
for (int i = 0; i < SPLITS; i++) {
total += benchmarkCallLocal();
}
System.out.println("CallLocal Total: " + total);
total = 0;
for (int i = 0; i < SPLITS; i++) {
total += benchmarkSplitCallback();
}
System.out.println("Callback Total: " + total);
total = 0;
for (int i = 0; i < SPLITS; i++) {
total += benchmarkConstructor();
}
System.out.println("Constructor Total: " + total);
total = 0;
for (int i = 0; i < SPLITS; i++) {
total += benchmarkConstructorLocal();
}
System.out.println("ConstructorLocal Total: " + total);
total = 0;
for (int i = 0; i < SPLITS; i++) {
total += benchmarkInheritanceConstructor();
}
System.out.println("InheritanceConstructor Total: " + total);
total = 0;
for (int i = 0; i < SPLITS; i++) {
total += benchmarkLargeMethodCall();
}
System.out.println("LargeMethodCall Total: " + total);
total = 0;
for (int i = 0; i < SPLITS; i++) {
total += benchmarkSplitCallbackLong();
}
System.out.println("CallbackLarge Total: " + total);
total = 0;
for (int i = 0; i < SPLITS; i++) {
total += benchmarkLargeMethodCallLocally();
}
System.out.println("LargeMethodCallLocal Total: " + total);
total = 0;
for (int i = 0; i < SPLITS; i++) {
total += benchmarkGuava();
}
System.out.println("Guava Total: " + total);
total = 0;
for (int i = 0; i < SPLITS; i++) {
total += benchmarkGuavaLocal();
}
System.out.println("GuavaLocal Total: " + total);
}
private long benchmarkCall() {
SplitClass split = new SplitClass(3);
long start = System.nanoTime();
for (int i = 0; i < ITERATIONS / SPLITS; i++) {
// Ensure no dead code elimination.
res = split.calculate(i);
}
long finish = System.nanoTime();
long timeElapsed = (finish - start) / 1000;
return timeElapsed;
}
private long benchmarkGuava() {
SplitClass split = new SplitClass(3);
long start = System.nanoTime();
res = split.guava(ITERATIONS / SPLITS / 10);
long finish = System.nanoTime();
long timeElapsed = (finish - start) / 1000;
return timeElapsed;
}
private long benchmarkGuavaLocal() {
long start = System.nanoTime();
res = guava(ITERATIONS / SPLITS / 10);
long finish = System.nanoTime();
long timeElapsed = (finish - start) / 1000;
return timeElapsed;
}
private long benchmarkCallLocal() {
long start = System.nanoTime();
for (int i = 0; i < ITERATIONS / SPLITS; i++) {
// Ensure no dead code elimination.
res = calculate(i);
}
long finish = System.nanoTime();
long timeElapsed = (finish - start) / 1000;
return timeElapsed;
}
private long benchmarkCallSplitLocal() {
SplitClass split = new SplitClass(3);
long start = System.nanoTime();
split.callSplitLocal();
long finish = System.nanoTime();
long timeElapsed = (finish - start) / 1000;
return timeElapsed;
}
private long benchmarkCallBaseline() {
SplitClass split = new SplitClass(3);
long start = System.nanoTime();
for (int i = 0; i < ITERATIONS / SPLITS; i++) {
int result = 2;
for (int j = 0; j < 42; j++) {
result += result + i;
}
res = result;
}
long finish = System.nanoTime();
long timeElapsed = (finish - start) / 1000;
return timeElapsed;
}
private long benchmarkInheritanceConstructor() {
List<SplitInheritBase> instances = new ArrayList<SplitInheritBase>();
long start = System.nanoTime();
for (int i = 0; i < ITERATIONS / SPLITS; i++) {
instances.add(new SplitInheritBase(i));
}
long finish = System.nanoTime();
long timeElapsed = (finish - start) / 1000;
return timeElapsed;
}
private long benchmarkConstructor() {
List<SplitClass> instances = new ArrayList<SplitClass>();
long start = System.nanoTime();
for (int i = 0; i < ITERATIONS / SPLITS; i++) {
instances.add(new SplitClass(i));
}
long finish = System.nanoTime();
long timeElapsed = (finish - start) / 1000;
return timeElapsed;
}
private long benchmarkConstructorLocal() {
List<BaseClass> instances = new ArrayList<BaseClass>();
long start = System.nanoTime();
for (int i = 0; i < ITERATIONS / SPLITS; i++) {
instances.add(new BaseClass(i));
}
long finish = System.nanoTime();
long timeElapsed = (finish - start) / 1000;
return timeElapsed;
}
private long benchmarkLargeMethodCall() {
SplitClass split = new SplitClass(3);
long start = System.nanoTime();
for (int i = 0; i < ITERATIONS / SPLITS; i++) {
// Ensure no dead code elimination.
res = split.largeMethod(i, i + 1);
}
long finish = System.nanoTime();
long timeElapsed = (finish - start) / 1000;
return timeElapsed;
}
private long benchmarkSplitCallback() {
SplitClass split = new SplitClass(3);
long start = System.nanoTime();
res = split.callBase();
long finish = System.nanoTime();
long timeElapsed = (finish - start) / 1000;
return timeElapsed;
}
private long benchmarkSplitCallbackLong() {
SplitClass split = new SplitClass(3);
long start = System.nanoTime();
res = split.callBaseLarge();
long finish = System.nanoTime();
long timeElapsed = (finish - start) / 1000;
return timeElapsed;
}
private long benchmarkLargeMethodCallLocally() {
BaseClass base = new BaseClass(3);
long start = System.nanoTime();
for (int i = 0; i < ITERATIONS / SPLITS; i++) {
// Ensure no dead code elimination.
res = base.largeMethod(i, i + 1);
}
long finish = System.nanoTime();
long timeElapsed = (finish - start) / 1000;
return timeElapsed;
}
public int guava(int iterations) {
for (int i = 0; i < iterations; i++) {
int result = 0;
ImmutableList<String> a = ImmutableList.of(
"foo",
"bar",
"foobar",
"last");
if (a.contains("foobar")) {
result++;
}
if (a.subList(0, 2).contains("last")) {
throw new RuntimeException("WAT");
}
result = a.size();
Multiset<String> set = ConcurrentHashMultiset.create();
for (int j = 0; j < 100; j++) {
set.add(a.get(j%4));
}
for (String s : a) {
result += set.count(s);
}
}
return 42;
}
public int calculate(int x) {
int result = 2;
for (int i = 0; i < 42; i++) {
result += res + x;
}
return result;
}
}