Add some dex splitter guava benchmarks

Change-Id: Ic60d8dabc824a7568963622ea47d3d6200cd441e
diff --git a/src/test/sampleApks/split/src/com/android/tools/r8/sample/split/R8Activity.java b/src/test/sampleApks/split/src/com/android/tools/r8/sample/split/R8Activity.java
index 307cac9..7ed223f 100644
--- a/src/test/sampleApks/split/src/com/android/tools/r8/sample/split/R8Activity.java
+++ b/src/test/sampleApks/split/src/com/android/tools/r8/sample/split/R8Activity.java
@@ -8,10 +8,23 @@
 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;
@@ -35,6 +48,14 @@
     }
     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();
@@ -83,6 +104,19 @@
     }
     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() {
@@ -97,6 +131,23 @@
     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++) {
@@ -108,6 +159,15 @@
     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();
@@ -198,6 +258,32 @@
     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++) {
diff --git a/src/test/sampleApks/split/src/com/android/tools/r8/sample/split/SplitClass.java b/src/test/sampleApks/split/src/com/android/tools/r8/sample/split/SplitClass.java
index b493326..d257c16 100644
--- a/src/test/sampleApks/split/src/com/android/tools/r8/sample/split/SplitClass.java
+++ b/src/test/sampleApks/split/src/com/android/tools/r8/sample/split/SplitClass.java
@@ -5,6 +5,9 @@
 package com.android.tools.r8.sample.split;
 
 import com.android.tools.r8.sample.split.R8Activity;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Multiset;
+import com.google.common.collect.ConcurrentHashMultiset;
 
 public class SplitClass {
   int initialValue;
@@ -13,8 +16,6 @@
     this.initialValue = initialValue;
   }
 
-
-
   public int calculate(int x) {
     int result = 2;
     for (int i = 0; i < 42; i++) {
@@ -23,6 +24,33 @@
     return result;
   }
 
+  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 largeMethod(int x, int y) {
     int a = x + y;
     int b;
@@ -104,6 +132,16 @@
     return a + b - c * x;
   }
 
+  public int callSplitLocal() {
+    SplitClass split = new SplitClass(initialValue);
+    for (int i = 0; i < R8Activity.ITERATIONS / R8Activity.SPLITS; i++) {
+      // Ensure no dead code elimination.
+      initialValue = split.calculate(i);
+    }
+    return initialValue;
+  }
+
+
   public int callBase() {
     BaseClass base = new BaseClass(initialValue);
     for (int i = 0; i < R8Activity.ITERATIONS / R8Activity.SPLITS; i++) {
diff --git a/tools/build_sample_apk.py b/tools/build_sample_apk.py
index b74356b..5f53196 100755
--- a/tools/build_sample_apk.py
+++ b/tools/build_sample_apk.py
@@ -85,6 +85,10 @@
 def get_android_jar(api):
   return os.path.join(utils.REPO_ROOT, ANDROID_JAR.format(api=api))
 
+def get_guava_jar():
+  return os.path.join(utils.REPO_ROOT,
+                      'third_party/gradle-plugin/com/google/guava/guava/22.0/guava-22.0.jar')
+
 def get_sample_dir(app):
   return os.path.join(utils.REPO_ROOT, 'src', 'test', 'sampleApks', app)
 
@@ -132,8 +136,11 @@
   with utils.ChangedWorkingDirectory(get_sample_dir(app)):
     files = glob.glob(SRC_LOCATION.format(app=app))
     command = [DEFAULT_JAVAC,
-               '-classpath', get_android_jar(api),
-               '-sourcepath', '%s:%s' % (get_src_path(app), get_gen_path(app)),
+               '-classpath', '%s:%s' % (get_android_jar(api), get_guava_jar()),
+               '-sourcepath', '%s:%s:%s' % (
+                   get_src_path(app),
+                   get_gen_path(app),
+                   get_guava_jar()),
                '-d', get_bin_path(app)]
     command.extend(files)
     utils.PrintCmd(command)
@@ -149,6 +156,8 @@
              '--classpath', get_android_jar(api),
              '--min-api', str(api)]
   command.extend(files)
+  command.append(get_guava_jar())
+
   utils.PrintCmd(command)
   subprocess.check_call(command)
 
@@ -253,7 +262,7 @@
   start(app)
   # We could do better here by continiously parsing the logcat for a marker, but
   # this works nicely with the current setup.
-  time.sleep(8)
+  time.sleep(12)
   kill(app)
   return float(store_or_print_benchmarks(stop_logcat(logcat), output_dir))