changeset 35:c65e5eaf3b0d

runtime.read|write tests.
author shade
date Fri, 02 Dec 2016 17:15:56 +0100
parents 73d0b304ec43
children 0844352df50d
files src/main/java/org/openjdk/gcbench/GCBench.java src/main/java/org/openjdk/gcbench/runtime/reads/Plain.java src/main/java/org/openjdk/gcbench/runtime/reads/Volatile.java src/main/java/org/openjdk/gcbench/runtime/reads/fields/Plain.java src/main/java/org/openjdk/gcbench/runtime/reads/fields/Volatile.java src/main/java/org/openjdk/gcbench/runtime/writes/Plain.java src/main/java/org/openjdk/gcbench/runtime/writes/Volatile.java src/main/java/org/openjdk/gcbench/tests/DimensionType.java src/main/java/org/openjdk/gcbench/tests/DimensionValues.java src/main/java/org/openjdk/gcbench/tests/DimensionalTest.java src/main/java/org/openjdk/gcbench/tests/Dimensions.java src/main/java/org/openjdk/gcbench/tests/MachineCntTest.java src/main/java/org/openjdk/gcbench/tests/Sequence.java src/main/java/org/openjdk/gcbench/util/Sinks.java
diffstat 14 files changed, 700 insertions(+), 292 deletions(-) [+]
line wrap: on
line diff
--- a/src/main/java/org/openjdk/gcbench/GCBench.java	Fri Dec 02 14:21:19 2016 +0100
+++ b/src/main/java/org/openjdk/gcbench/GCBench.java	Fri Dec 02 17:15:56 2016 +0100
@@ -5,8 +5,6 @@
 import joptsimple.OptionSpec;
 import org.openjdk.gcbench.tests.*;
 import org.openjdk.jmh.annotations.Threads;
-import org.openjdk.jmh.profile.GCProfiler;
-import org.openjdk.jmh.profile.SafepointsProfiler;
 import org.openjdk.jmh.runner.RunnerException;
 import org.openjdk.jmh.runner.options.*;
 import org.openjdk.jmh.util.Utils;
@@ -93,8 +91,6 @@
         Options opts = new OptionsBuilder()
                 .detectJvmArgs()
                 .threads(Threads.MAX)
-                .addProfiler(GCProfiler.class)
-                .addProfiler(SafepointsProfiler.class)
                 .verbosity(VerboseMode.SILENT)
                 .shouldFailOnError(true)
                 .build();
@@ -126,8 +122,8 @@
                         .warmupIterations(3)
                         .warmupTime(TimeValue.seconds(1))
                         .measurementIterations(1)
-                        .measurementTime(TimeValue.seconds(10))
-                        .forks(1)
+                        .measurementTime(TimeValue.seconds(3))
+                        .forks(3)
                         .build();
                 break;
             case tough:
@@ -279,6 +275,42 @@
                     Dimensions.size(Sequence.powersOfTen_Sub(100, 100000))
             ));
         }
+
+        {
+            String groupDescr = "Estimates the runtime overhead for reads. These costs include all the infrastructural " +
+                    "overheads too, and therefore the score differences matter, not their absolute values. This test " +
+                    "is single-threaded. ";
+
+            tests.add(new MachineCntTest(baseOpts, org.openjdk.gcbench.runtime.reads.Plain.class,
+                    "runtime.reads.plain", groupDescr + "Reads plain Java fields.",
+                    Dimensions.jvmMode(),
+                    Dimensions.javaType()
+            ));
+
+            tests.add(new MachineCntTest(baseOpts, org.openjdk.gcbench.runtime.reads.Volatile.class,
+                    "runtime.reads.volatile", groupDescr + "Reads volatile Java fields.",
+                    Dimensions.jvmMode(),
+                    Dimensions.javaType()
+            ));
+        }
+
+        {
+            String groupDescr = "Estimates the runtime overhead for цкшеуы. These costs include all the infrastructural " +
+                    "overheads too, and therefore the score differences matter, not their absolute values. This test " +
+                    "is single-threaded. ";
+
+            tests.add(new MachineCntTest(baseOpts, org.openjdk.gcbench.runtime.writes.Plain.class,
+                    "runtime.writes.plain", groupDescr + "Writes plain Java fields.",
+                    Dimensions.jvmMode(),
+                    Dimensions.javaType()
+            ));
+
+            tests.add(new MachineCntTest(baseOpts, org.openjdk.gcbench.runtime.writes.Volatile.class,
+                    "runtime.writes.volatile", groupDescr + "Writes volatiel Java fields.",
+                    Dimensions.jvmMode(),
+                    Dimensions.javaType()
+            ));
+        }
     }
 
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/org/openjdk/gcbench/runtime/reads/Plain.java	Fri Dec 02 17:15:56 2016 +0100
@@ -0,0 +1,97 @@
+package org.openjdk.gcbench.runtime.reads;
+
+import org.openjdk.jmh.annotations.*;
+
+import java.util.concurrent.TimeUnit;
+
+import static org.openjdk.gcbench.util.Sinks.sink;
+
+@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(1)
+@State(Scope.Benchmark)
+public class Plain {
+
+    Target target;
+
+    @Setup
+    public void setup() {
+        target = new Target();
+    }
+
+    @Benchmark
+    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
+    public void test_none() {
+        sink();
+    }
+
+    @Benchmark
+    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
+    public void test_boolean() {
+        sink(target.f_boolean);
+    }
+
+    @Benchmark
+    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
+    public void test_byte() {
+        sink(target.f_byte);
+    }
+
+    @Benchmark
+    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
+    public void test_char() {
+        sink(target.f_char);
+    }
+
+    @Benchmark
+    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
+    public void test_short() {
+        sink(target.f_short);
+    }
+
+    @Benchmark
+    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
+    public void test_int() {
+        sink(target.f_int);
+    }
+
+    @Benchmark
+    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
+    public void test_float() {
+        sink(target.f_float);
+    }
+
+    @Benchmark
+    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
+    public void test_long() {
+        sink(target.f_long);
+    }
+
+    @Benchmark
+    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
+    public void test_double() {
+        sink(target.f_double);
+    }
+
+    @Benchmark
+    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
+    public void test_Object() {
+        sink(target.f_Object);
+    }
+
+    static class Target {
+        boolean f_boolean;
+        byte f_byte;
+        short f_short;
+        char f_char;
+        int f_int;
+        float f_float;
+        long f_long;
+        double f_double;
+        Object f_Object;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/org/openjdk/gcbench/runtime/reads/Volatile.java	Fri Dec 02 17:15:56 2016 +0100
@@ -0,0 +1,97 @@
+package org.openjdk.gcbench.runtime.reads;
+
+import org.openjdk.jmh.annotations.*;
+
+import java.util.concurrent.TimeUnit;
+
+import static org.openjdk.gcbench.util.Sinks.sink;
+
+@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(1)
+@State(Scope.Benchmark)
+public class Volatile {
+
+    Target target;
+
+    @Setup
+    public void setup() {
+        target = new Target();
+    }
+
+    @Benchmark
+    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
+    public void test_none() {
+        sink();
+    }
+
+    @Benchmark
+    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
+    public void test_boolean() {
+        sink(target.f_boolean);
+    }
+
+    @Benchmark
+    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
+    public void test_byte() {
+        sink(target.f_byte);
+    }
+
+    @Benchmark
+    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
+    public void test_char() {
+        sink(target.f_char);
+    }
+
+    @Benchmark
+    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
+    public void test_short() {
+        sink(target.f_short);
+    }
+
+    @Benchmark
+    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
+    public void test_int() {
+        sink(target.f_int);
+    }
+
+    @Benchmark
+    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
+    public void test_float() {
+        sink(target.f_float);
+    }
+
+    @Benchmark
+    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
+    public void test_long() {
+        sink(target.f_long);
+    }
+
+    @Benchmark
+    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
+    public void test_double() {
+        sink(target.f_double);
+    }
+
+    @Benchmark
+    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
+    public void test_Object() {
+        sink(target.f_Object);
+    }
+
+    static class Target {
+        volatile boolean f_boolean;
+        volatile byte f_byte;
+        volatile short f_short;
+        volatile char f_char;
+        volatile int f_int;
+        volatile float f_float;
+        volatile long f_long;
+        volatile double f_double;
+        volatile Object f_Object;
+    }
+
+}
--- a/src/main/java/org/openjdk/gcbench/runtime/reads/fields/Plain.java	Fri Dec 02 14:21:19 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,116 +0,0 @@
-package org.openjdk.gcbench.runtime.reads.fields;
-
-import org.openjdk.jmh.annotations.*;
-
-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(1)
-@State(Scope.Benchmark)
-public class Plain {
-
-    Target target;
-
-    @Setup
-    public void setup() {
-        target = new Target();
-    }
-
-    @Benchmark
-    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
-    public void test_boolean() {
-        sink(target.f_boolean);
-    }
-
-    @Benchmark
-    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
-    public void test_byte() {
-        sink(target.f_byte);
-    }
-
-    @Benchmark
-    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
-    public void test_char() {
-        sink(target.f_char);
-    }
-
-    @Benchmark
-    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
-    public void test_short() {
-        sink(target.f_short);
-    }
-
-    @Benchmark
-    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
-    public void test_int() {
-        sink(target.f_int);
-    }
-
-    @Benchmark
-    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
-    public void test_float() {
-        sink(target.f_float);
-    }
-
-    @Benchmark
-    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
-    public void test_long() {
-        sink(target.f_long);
-    }
-
-    @Benchmark
-    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
-    public void test_double() {
-        sink(target.f_double);
-    }
-
-    @Benchmark
-    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
-    public void test_Object() {
-        sink(target.f_Object);
-    }
-
-    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
-    private void sink(boolean i) {}
-
-    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
-    private void sink(byte i) {}
-
-    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
-    private void sink(short i) {}
-
-    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
-    private void sink(char i) {}
-
-    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
-    private void sink(int i) {}
-
-    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
-    private void sink(float i) {}
-
-    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
-    private void sink(long i) {}
-
-    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
-    private void sink(double i) {}
-
-    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
-    private void sink(Object i) {}
-
-    static class Target {
-        boolean f_boolean;
-        byte f_byte;
-        short f_short;
-        char f_char;
-        int f_int;
-        float f_float;
-        long f_long;
-        double f_double;
-        Object f_Object;
-    }
-
-}
--- a/src/main/java/org/openjdk/gcbench/runtime/reads/fields/Volatile.java	Fri Dec 02 14:21:19 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,116 +0,0 @@
-package org.openjdk.gcbench.runtime.reads.fields;
-
-import org.openjdk.jmh.annotations.*;
-
-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(1)
-@State(Scope.Benchmark)
-public class Volatile {
-
-    Target target;
-
-    @Setup
-    public void setup() {
-        target = new Target();
-    }
-
-    @Benchmark
-    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
-    public void test_boolean() {
-        sink(target.f_boolean);
-    }
-
-    @Benchmark
-    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
-    public void test_byte() {
-        sink(target.f_byte);
-    }
-
-    @Benchmark
-    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
-    public void test_char() {
-        sink(target.f_char);
-    }
-
-    @Benchmark
-    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
-    public void test_short() {
-        sink(target.f_short);
-    }
-
-    @Benchmark
-    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
-    public void test_int() {
-        sink(target.f_int);
-    }
-
-    @Benchmark
-    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
-    public void test_float() {
-        sink(target.f_float);
-    }
-
-    @Benchmark
-    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
-    public void test_long() {
-        sink(target.f_long);
-    }
-
-    @Benchmark
-    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
-    public void test_double() {
-        sink(target.f_double);
-    }
-
-    @Benchmark
-    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
-    public void test_Object() {
-        sink(target.f_Object);
-    }
-
-    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
-    private void sink(boolean i) {}
-
-    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
-    private void sink(byte i) {}
-
-    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
-    private void sink(short i) {}
-
-    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
-    private void sink(char i) {}
-
-    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
-    private void sink(int i) {}
-
-    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
-    private void sink(float i) {}
-
-    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
-    private void sink(long i) {}
-
-    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
-    private void sink(double i) {}
-
-    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
-    private void sink(Object i) {}
-
-    static class Target {
-        volatile boolean f_boolean;
-        volatile byte f_byte;
-        volatile short f_short;
-        volatile char f_char;
-        volatile int f_int;
-        volatile float f_float;
-        volatile long f_long;
-        volatile double f_double;
-        volatile Object f_Object;
-    }
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/org/openjdk/gcbench/runtime/writes/Plain.java	Fri Dec 02 17:15:56 2016 +0100
@@ -0,0 +1,96 @@
+package org.openjdk.gcbench.runtime.writes;
+
+import org.openjdk.jmh.annotations.*;
+
+import java.util.concurrent.TimeUnit;
+
+import static org.openjdk.gcbench.util.Sinks.sink;
+
+@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(1)
+@State(Scope.Benchmark)
+public class Plain {
+
+    Target target;
+
+    @Setup
+    public void setup() {
+        target = new Target();
+    }
+
+    @Benchmark
+    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
+    public void test_none() {
+    }
+
+    @Benchmark
+    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
+    public void test_boolean() {
+        target.f_boolean = true;
+    }
+
+    @Benchmark
+    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
+    public void test_byte() {
+        target.f_byte = 42;
+    }
+
+    @Benchmark
+    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
+    public void test_char() {
+        target.f_char = 'A';
+    }
+
+    @Benchmark
+    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
+    public void test_short() {
+        target.f_short = 42;
+    }
+
+    @Benchmark
+    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
+    public void test_int() {
+        target.f_int = 42;
+    }
+
+    @Benchmark
+    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
+    public void test_float() {
+        target.f_float = 42f;
+    }
+
+    @Benchmark
+    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
+    public void test_long() {
+        target.f_long = 42L;
+    }
+
+    @Benchmark
+    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
+    public void test_double() {
+        target.f_double = 42D;
+    }
+
+    @Benchmark
+    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
+    public void test_Object() {
+        target.f_Object = target;
+    }
+
+    static class Target {
+        boolean f_boolean;
+        byte f_byte;
+        short f_short;
+        char f_char;
+        int f_int;
+        float f_float;
+        long f_long;
+        double f_double;
+        Object f_Object;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/org/openjdk/gcbench/runtime/writes/Volatile.java	Fri Dec 02 17:15:56 2016 +0100
@@ -0,0 +1,96 @@
+package org.openjdk.gcbench.runtime.writes;
+
+import org.openjdk.jmh.annotations.*;
+
+import java.util.concurrent.TimeUnit;
+
+import static org.openjdk.gcbench.util.Sinks.sink;
+
+@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(1)
+@State(Scope.Benchmark)
+public class Volatile {
+
+    Target target;
+
+    @Setup
+    public void setup() {
+        target = new Target();
+    }
+
+    @Benchmark
+    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
+    public void test_none() {
+    }
+
+    @Benchmark
+    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
+    public void test_boolean() {
+        target.f_boolean = true;
+    }
+
+    @Benchmark
+    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
+    public void test_byte() {
+        target.f_byte = 42;
+    }
+
+    @Benchmark
+    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
+    public void test_char() {
+        target.f_char = 'A';
+    }
+
+    @Benchmark
+    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
+    public void test_short() {
+        target.f_short = 42;
+    }
+
+    @Benchmark
+    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
+    public void test_int() {
+        target.f_int = 42;
+    }
+
+    @Benchmark
+    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
+    public void test_float() {
+        target.f_float = 42f;
+    }
+
+    @Benchmark
+    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
+    public void test_long() {
+        target.f_long = 42L;
+    }
+
+    @Benchmark
+    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
+    public void test_double() {
+        target.f_double = 42D;
+    }
+
+    @Benchmark
+    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
+    public void test_Object() {
+        target.f_Object = target;
+    }
+
+    static class Target {
+        volatile boolean f_boolean;
+        volatile byte f_byte;
+        volatile short f_short;
+        volatile char f_char;
+        volatile int f_int;
+        volatile float f_float;
+        volatile long f_long;
+        volatile double f_double;
+        volatile Object f_Object;
+    }
+
+}
--- a/src/main/java/org/openjdk/gcbench/tests/DimensionType.java	Fri Dec 02 14:21:19 2016 +0100
+++ b/src/main/java/org/openjdk/gcbench/tests/DimensionType.java	Fri Dec 02 17:15:56 2016 +0100
@@ -10,6 +10,10 @@
 
     THREADS("Threads"),
 
+    JVM_MODE("Mode"),
+
+    JAVA_TYPE("Type"),
+
     ;
 
     private final String label;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/org/openjdk/gcbench/tests/DimensionValues.java	Fri Dec 02 17:15:56 2016 +0100
@@ -0,0 +1,41 @@
+package org.openjdk.gcbench.tests;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+class DimensionValues {
+    Object[] values;
+
+    public static List<DimensionValues> product(Dimension... dimensions) {
+        List<DimensionValues> values = new ArrayList<>();
+
+        for (Dimension d : dimensions) {
+            List<DimensionValues> nextValues = new ArrayList<>();
+            if (values.isEmpty()) {
+                for (Object v : d.seq()) {
+                    nextValues.add(new DimensionValues(new Object[]{v}));
+                }
+            } else {
+                for (DimensionValues vs : values) {
+                    for (Object v : d.seq()) {
+                        nextValues.add(vs.addNew(v));
+                    }
+                }
+            }
+            values = nextValues;
+        }
+        return values;
+    }
+
+
+    public DimensionValues(Object[] values) {
+        this.values = values;
+    }
+
+    DimensionValues addNew(Object value) {
+        Object[] nv = Arrays.copyOf(values, values.length + 1);
+        nv[nv.length - 1] = value;
+        return new DimensionValues(nv);
+    }
+}
--- a/src/main/java/org/openjdk/gcbench/tests/DimensionalTest.java	Fri Dec 02 14:21:19 2016 +0100
+++ b/src/main/java/org/openjdk/gcbench/tests/DimensionalTest.java	Fri Dec 02 17:15:56 2016 +0100
@@ -1,5 +1,7 @@
 package org.openjdk.gcbench.tests;
 
+import org.openjdk.jmh.profile.GCProfiler;
+import org.openjdk.jmh.profile.SafepointsProfiler;
 import org.openjdk.jmh.results.Result;
 import org.openjdk.jmh.results.RunResult;
 import org.openjdk.jmh.runner.Runner;
@@ -8,9 +10,6 @@
 import org.openjdk.jmh.runner.options.Options;
 import org.openjdk.jmh.runner.options.OptionsBuilder;
 
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
 import java.util.Map;
 
 public class DimensionalTest extends AbstractTest {
@@ -56,35 +55,39 @@
                 "TTSP (sum, 99%, 99.9%, 99.99%)"
         );
 
-        int lastKeyVal = -1;
+        Object lastKeyVal = null;
 
-        for (DimensionValues values : product()) {
+        for (DimensionValues values : DimensionValues.product(dimensions)) {
             ChainedOptionsBuilder builder = new OptionsBuilder()
                     .parent(baseOpts)
+                    .addProfiler(GCProfiler.class)
+                    .addProfiler(SafepointsProfiler.class)
                     .include(benchmark.getName());
 
             int heapSize = -1;
             int lds = -1;
 
-            int keyVal = -1;
+            Object keyVal = -1;
             for (int i = 0; i < dimensions.length; i++) {
                 Dimension d = dimensions[i];
-                int value = values.values[i];
+                Object value = values.values[i];
                 if (i == dimensions.length - 2) {
                     keyVal = value;
                 }
 
+                int intValue = Integer.valueOf(value.toString());
+
                 switch (d.type()) {
                     case HEAPSIZE:
                         builder = builder.jvmArgsAppend("-Xmx" + value + "m", "-Xms" + value + "m");
-                        heapSize = value;
+                        heapSize = intValue;
                         break;
                     case LDS:
                         builder = builder.param("ldsMB", String.valueOf(value));
-                        lds = value;
+                        lds = intValue;
                         break;
                     case THREADS:
-                        builder = builder.threads(value);
+                        builder = builder.threads(intValue);
                         break;
                     case SIZE:
                         builder = builder.param("size", String.valueOf(value));
@@ -138,7 +141,7 @@
     private void runWith(DimensionValues values, Options opts, int rate) {
         pw.print("  ");
 
-        for (int v : values.values) {
+        for (Object v : values.values) {
             pw.printf("%-10s ", v);
         }
 
@@ -199,39 +202,4 @@
         }
     }
 
-    private List<DimensionValues> product() {
-        List<DimensionValues> values = new ArrayList<>();
-
-        for (Dimension d : dimensions) {
-            List<DimensionValues> nextValues = new ArrayList<>();
-            if (values.isEmpty()) {
-                for (int v : d.seq()) {
-                    nextValues.add(new DimensionValues(new int[]{v}));
-                }
-            } else {
-                for (DimensionValues vs : values) {
-                    for (int v : d.seq()) {
-                        nextValues.add(vs.addNew(v));
-                    }
-                }
-            }
-            values = nextValues;
-        }
-        return values;
-    }
-
-    private static class DimensionValues {
-        int[] values;
-
-        public DimensionValues(int[] values) {
-            this.values = values;
-        }
-
-        DimensionValues addNew(int value) {
-            int[] nv = Arrays.copyOf(values, values.length + 1);
-            nv[nv.length - 1] = value;
-            return new DimensionValues(nv);
-        }
-    }
-
 }
--- a/src/main/java/org/openjdk/gcbench/tests/Dimensions.java	Fri Dec 02 14:21:19 2016 +0100
+++ b/src/main/java/org/openjdk/gcbench/tests/Dimensions.java	Fri Dec 02 17:15:56 2016 +0100
@@ -27,4 +27,11 @@
         return new Dimension(DimensionType.THREADS, Sequence.powersOfTwo(1, Runtime.getRuntime().availableProcessors()));
     }
 
+    public static Dimension jvmMode() {
+        return new Dimension(DimensionType.JVM_MODE, Sequence.jvmModes());
+    }
+
+    public static Dimension javaType() {
+        return new Dimension(DimensionType.JAVA_TYPE, Sequence.javaType());
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/org/openjdk/gcbench/tests/MachineCntTest.java	Fri Dec 02 17:15:56 2016 +0100
@@ -0,0 +1,137 @@
+package org.openjdk.gcbench.tests;
+
+import org.openjdk.jmh.profile.LinuxPerfNormProfiler;
+import org.openjdk.jmh.results.Result;
+import org.openjdk.jmh.results.RunResult;
+import org.openjdk.jmh.runner.Runner;
+import org.openjdk.jmh.runner.RunnerException;
+import org.openjdk.jmh.runner.options.ChainedOptionsBuilder;
+import org.openjdk.jmh.runner.options.Options;
+import org.openjdk.jmh.runner.options.OptionsBuilder;
+
+import java.util.Map;
+
+public class MachineCntTest extends AbstractTest {
+
+    private final Dimension[] dimensions;
+
+    public MachineCntTest(Options baseOpts, Class<?> benchmark, String label, String description,
+                           Dimension... dimensions) {
+        super(baseOpts, label, benchmark, description);
+        this.dimensions = dimensions;
+    }
+
+    @Override
+    protected void doRun() {
+        pw.println("  Test dimensions: ");
+        for (Dimension d : dimensions) {
+            pw.print("    ");
+            pw.println(d.toString());
+        }
+        pw.println();
+
+        pw.print("  ");
+
+        for (Dimension d : dimensions) {
+            pw.printf("%-30s ", d.label());
+        }
+
+        pw.printf("%-35s %-25s %-25s %-25s %n",
+                "Performance",
+                "Instructions",
+                "Cycles",
+                "Branches"
+        );
+
+        Object lastKeyVal = null;
+
+        for (DimensionValues values : DimensionValues.product(dimensions)) {
+            ChainedOptionsBuilder builder = new OptionsBuilder()
+                    .parent(baseOpts)
+                    .threads(1)
+                    .addProfiler(LinuxPerfNormProfiler.class);
+
+
+            Object keyVal = -1;
+            for (int i = 0; i < dimensions.length; i++) {
+                Dimension d = dimensions[i];
+                Object value = values.values[i];
+                if (i == dimensions.length - 2) {
+                    keyVal = value;
+                }
+
+                switch (d.type()) {
+                    case JVM_MODE:
+                        builder = builder.jvmArgsAppend(String.valueOf(value));
+                        break;
+                    case JAVA_TYPE:
+                        builder = builder.include(benchmark.getName() + ".test_" + value);
+                        break;
+                    default:
+                        throw new IllegalStateException("Unknown dimension: " + d);
+                }
+            }
+
+            if (lastKeyVal != keyVal) {
+                pw.println();
+                lastKeyVal = keyVal;
+            }
+
+            runWith(values, builder.build());
+        }
+    }
+
+    private void runWith(DimensionValues values, Options opts) {
+        pw.print("  ");
+
+        for (Object v : values.values) {
+            pw.printf("%-30s ", v);
+        }
+
+        try {
+            RunResult result = new Runner(opts).runSingle();
+
+            Result prim = result.getPrimaryResult();
+            Map<String, Result> sec = result.getSecondaryResults();
+
+            pw.printf("%-35s %-25s %-25s %-25s%n",
+                    shortVal(prim),
+                    shortVal(sec.get("instructions")),
+                    shortVal(sec.get("cycles")),
+                    shortVal(sec.get("branches"))
+            );
+        } catch (RunnerException e) {
+            pw.print("FAILED: ");
+            Throwable cause = e.getCause();
+            if (cause != null) {
+                for (Throwable t : cause.getSuppressed()) {
+                    pw.print(t.getMessage() + " ");
+                }
+            } else {
+                pw.println(" unknown error");
+                e.printStackTrace(pw);
+            }
+            pw.println();
+        }
+    }
+
+    private String shortVal(Result r) {
+        if (r != null) {
+            if (!Double.isNaN(r.getScoreError())) {
+                return String.format("%.3f ± %.3f %s", r.getScore(), r.getScoreError(), r.getScoreUnit());
+            } else {
+                return String.format("%.3f %s", r.getScore(), r.getScoreUnit());
+            }
+        } else {
+            return "-";
+        }
+    }
+
+    private String latencyVal(Result r) {
+        if (r != null && !Double.isNaN(r.getScore())) {
+            return String.format("%.3f %s", r.getScore(), r.getScoreUnit());
+        } else {
+            return "-";
+        }
+    }
+}
--- a/src/main/java/org/openjdk/gcbench/tests/Sequence.java	Fri Dec 02 14:21:19 2016 +0100
+++ b/src/main/java/org/openjdk/gcbench/tests/Sequence.java	Fri Dec 02 17:15:56 2016 +0100
@@ -1,16 +1,17 @@
 package org.openjdk.gcbench.tests;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Iterator;
 import java.util.List;
 
-public class Sequence implements Iterable<Integer> {
+public class Sequence implements Iterable<Object> {
 
     private final String descr;
-    private final List<Integer> vals;
+    private final List<Object> vals;
 
     public static Sequence powersOfTen_Sub(int min, int max) {
-        List<Integer> vs = new ArrayList<>();
+        List<Object> vs = new ArrayList<>();
         for (int v = min; v <= max; v *= 10) {
             for (int t = 1; t <= 5; t++) {
                 int n = v * t * 2;
@@ -23,7 +24,7 @@
     }
 
     public static Sequence powersOfTen(int min, int max) {
-        List<Integer> vs = new ArrayList<>();
+        List<Object> vs = new ArrayList<>();
         for (int v = min; v <= max; v *= 10) {
             vs.add(v);
         }
@@ -31,7 +32,7 @@
     }
 
     public static Sequence powersOfTwo(int min, int max) {
-        List<Integer> vs = new ArrayList<>();
+        List<Object> vs = new ArrayList<>();
         for (int v = min; v <= max; v *= 2) {
             vs.add(v);
         }
@@ -39,7 +40,7 @@
     }
 
     public static Sequence steps(int min, int max, int steps) {
-        List<Integer> vs = new ArrayList<>();
+        List<Object> vs = new ArrayList<>();
         int stepSize = (max - min) / steps;
         for (int v = min; v <= max; v += stepSize) {
             vs.add(v);
@@ -47,13 +48,13 @@
         return new Sequence("[" + min + ", " + max + "], step size = " + stepSize, vs);
     }
 
-    private Sequence(String descr, List<Integer> vals) {
+    private Sequence(String descr, List<Object> vals) {
         this.descr = descr;
         this.vals = vals;
     }
 
     @Override
-    public Iterator<Integer> iterator() {
+    public Iterator<Object> iterator() {
         return vals.iterator();
     }
 
@@ -61,4 +62,31 @@
     public String toString() {
         return descr;
     }
+
+    public static Sequence jvmModes() {
+        return new Sequence("available JVM modes",
+                Arrays.asList(
+                        "-Xint",
+                        "-XX:TieredStopAtLevel=1",
+//                        "-XX:TieredStopAtLevel=2",
+//                        "-XX:TieredStopAtLevel=3",
+                        "-XX:TieredStopAtLevel=4"
+                ));
+    }
+
+    public static Sequence javaType() {
+        return new Sequence("Java types",
+                Arrays.asList(
+                        "none",
+                        "boolean",
+                        "byte",
+                        "short",
+                        "char",
+                        "int",
+                        "float",
+                        "long",
+                        "double",
+                        "Object"
+                ));
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/org/openjdk/gcbench/util/Sinks.java	Fri Dec 02 17:15:56 2016 +0100
@@ -0,0 +1,37 @@
+package org.openjdk.gcbench.util;
+
+import org.openjdk.jmh.annotations.CompilerControl;
+
+public class Sinks {
+
+    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
+    public static void sink() {}
+
+    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
+    public static void sink(boolean i) {}
+
+    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
+    public static void sink(byte i) {}
+
+    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
+    public static void sink(short i) {}
+
+    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
+    public static void sink(char i) {}
+
+    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
+    public static void sink(int i) {}
+
+    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
+    public static void sink(float i) {}
+
+    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
+    public static void sink(long i) {}
+
+    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
+    public static void sink(double i) {}
+
+    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
+    public static void sink(Object i) {}
+
+}