changeset 2:89dd4770a404

StringTable/ThreadVarRoots benchmarks.
author shade
date Thu, 24 Nov 2016 19:47:31 +0100
parents 06dbd0d0fe69
children b993a8a07b28
files src/main/java/org/openjdk/gcbench/GCBench.java src/main/java/org/openjdk/gcbench/roots/StringTableRoots.java src/main/java/org/openjdk/gcbench/roots/ThreadVarRoots.java
diffstat 3 files changed, 152 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/src/main/java/org/openjdk/gcbench/GCBench.java	Thu Nov 24 10:41:10 2016 +0100
+++ b/src/main/java/org/openjdk/gcbench/GCBench.java	Thu Nov 24 19:47:31 2016 +0100
@@ -7,6 +7,7 @@
 import org.openjdk.gcbench.alloc.ratelimited.PrimArray;
 import org.openjdk.gcbench.alloc.ratelimited.RefArray;
 import org.openjdk.gcbench.fragger.ArrayFragger;
+import org.openjdk.gcbench.roots.StringTableRoots;
 import org.openjdk.gcbench.roots.Synchronizers;
 import org.openjdk.gcbench.util.Dummy;
 import org.openjdk.jmh.annotations.Threads;
@@ -137,6 +138,7 @@
         alloc_ratelimit,
         fraggers,
         roots_synch,
+        roots_strings,
     }
 
     public enum Mode {
@@ -159,6 +161,9 @@
                 case roots_synch:
                     runRoots_Synch();
                     break;
+                case roots_strings:
+                    runRoots_Strings();
+                    break;
                 default:
                     throw new IllegalStateException("Unknown test: " + test);
             }
@@ -169,6 +174,14 @@
         pw.println("=== ROOTSET: SYNCHRONIZER ROOTS");
         pw.println();
 
+        pw.printf("%-10s %-45s %-45s %-52s      %-52s %n",
+                "size",
+                "performance",
+                "allocation rate",
+                "pauses (sum, 99%, 99.9%, 99.99%)",
+                "ttsp (sum, 99%, 99.9%, 99.99%)"
+        );
+
         for (int size = 0; size < 40000; size++) {
             Options opts = new OptionsBuilder()
                     .parent(baseOpts)
@@ -177,28 +190,62 @@
                     .param("size", String.valueOf(size))
                     .build();
 
-            try {
-                RunResult result = new Runner(opts).runSingle();
+            doWithSize(size, opts);
+        }
+    }
+
+    private void runRoots_Strings() {
+        pw.println("=== ROOTSET: STRING ROOTS");
+        pw.println();
 
-                Result prim = result.getPrimaryResult();
-                Map<String, Result> sec = result.getSecondaryResults();
+        Utils.reflow(pw,
+                "The test interns the ${size} number of distinct Strings before the run, and then tries to continuously allocate Objects " +
+                        "to see if the String table affects garbage collection, e.g. by being the part of the root set.",
+                80, 2);
+        pw.println();
+
+        pw.printf("%-10s %-45s %-45s %-52s      %-52s %n",
+                "size",
+                "performance",
+                "allocation rate",
+                "pauses (sum, 99%, 99.9%, 99.99%)",
+                "ttsp (sum, 99%, 99.9%, 99.99%)"
+        );
 
-                pw.printf("%-10d %-45s %-45s %12s %12s %12s %12s      %12s %12s %12s %12s %n",
-                        size,
-                        prim,
-                        sec.get("·gc.alloc.rate"),
-                        sec.get("·safepoints.pause"),
-                        sec.get("·safepoints.pause.p0.99"),
-                        sec.get("·safepoints.pause.p0.999"),
-                        sec.get("·safepoints.pause.p0.9999"),
-                        sec.get("·safepoints.ttsp"),
-                        sec.get("·safepoints.ttsp.p0.99"),
-                        sec.get("·safepoints.ttsp.p0.999"),
-                        sec.get("·safepoints.ttsp.p0.9999")
-                );
-            } catch (RunnerException e) {
-                // OOME, fail
-            }
+        for (int size = 1; size <= 100_000_000; size *= 2) {
+            Options opts = new OptionsBuilder()
+                    .parent(baseOpts)
+                    .include(StringTableRoots.class.getCanonicalName())
+                    .threads(Threads.MAX)
+                    .param("size", String.valueOf(size))
+                    .build();
+
+            doWithSize(size, opts);
+        }
+    }
+
+    private void doWithSize(int size, Options opts) {
+        try {
+            RunResult result = new Runner(opts).runSingle();
+
+            Result prim = result.getPrimaryResult();
+            Map<String, Result> sec = result.getSecondaryResults();
+
+            pw.printf("%-10d %-45s %-45s %12s %12s %12s %12s      %12s %12s %12s %12s %n",
+                    size,
+                    prim,
+                    sec.get("·gc.alloc.rate"),
+                    sec.get("·safepoints.pause"),
+                    sec.get("·safepoints.pause.p0.99"),
+                    sec.get("·safepoints.pause.p0.999"),
+                    sec.get("·safepoints.pause.p0.9999"),
+                    sec.get("·safepoints.ttsp"),
+                    sec.get("·safepoints.ttsp.p0.99"),
+                    sec.get("·safepoints.ttsp.p0.999"),
+                    sec.get("·safepoints.ttsp.p0.9999")
+            );
+        } catch (RunnerException e) {
+            // OOME, fail
         }
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/org/openjdk/gcbench/roots/StringTableRoots.java	Thu Nov 24 19:47:31 2016 +0100
@@ -0,0 +1,38 @@
+package org.openjdk.gcbench.roots;
+
+import org.openjdk.jmh.annotations.*;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+@Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
+@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
+@Fork(1)
+@BenchmarkMode(Mode.AverageTime)
+@OutputTimeUnit(TimeUnit.NANOSECONDS)
+@Threads(Threads.MAX)
+@State(Scope.Benchmark)
+public class StringTableRoots {
+
+    List<String> list;
+
+    @Param({"100000"})
+    private int size;
+
+    @Setup
+    public void setup() {
+        list = new ArrayList<>();
+        for (int c = 0; c < size; c++) {
+            String s = "" + c + "root";
+            list.add(s.intern());
+        }
+    }
+
+    @Benchmark
+    public Object test() throws InterruptedException {
+        // allocation pressure to trigger GCs
+        return new Object();
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/org/openjdk/gcbench/roots/ThreadVarRoots.java	Thu Nov 24 19:47:31 2016 +0100
@@ -0,0 +1,47 @@
+package org.openjdk.gcbench.roots;
+
+import org.openjdk.jmh.annotations.*;
+import org.openjdk.jmh.infra.Blackhole;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+@Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
+@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS)
+@Fork(value = 1, jvmArgsAppend = "-Xss32m")
+@BenchmarkMode(Mode.AverageTime)
+@OutputTimeUnit(TimeUnit.MICROSECONDS)
+@Threads(Threads.MAX)
+@State(Scope.Benchmark)
+public class ThreadVarRoots {
+
+    List<Object> list;
+
+    @Param({"100000"})
+    private int size;
+
+    @Setup
+    public void setup() {
+        list = new ArrayList<>();
+        for (int c = 0; c < size; c++) {
+            list.add(new Object());
+        }
+    }
+
+    @Benchmark
+    public Object test() throws InterruptedException {
+        return recursiveLocal(list, 0, null);
+    }
+
+    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
+    private Object recursiveLocal(List<Object> list, int i, Object o) {
+        if (i < list.size()) {
+            return recursiveLocal(list, i + 1, list.get(i));
+        } else {
+            // Allocation pressure to trigger GCs.
+            return new Object();
+        }
+    }
+
+}