changeset 30:4a1bca166d6c

Progress: Plain/volatile read barriers tests for fields.
author shade
date Thu, 01 Dec 2016 14:27:24 +0100
parents af1694c8b2a2
children 048984ee8010
files src/main/java/org/openjdk/gcbench/runtime/reads/ReadBarriersFields.java src/main/java/org/openjdk/gcbench/runtime/reads/fields/Plain.java src/main/java/org/openjdk/gcbench/runtime/reads/fields/Volatile.java
diffstat 3 files changed, 232 insertions(+), 140 deletions(-) [+]
line wrap: on
line diff
--- a/src/main/java/org/openjdk/gcbench/runtime/reads/ReadBarriersFields.java	Thu Dec 01 11:18:39 2016 +0100
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,140 +0,0 @@
-package org.openjdk.gcbench.runtime.reads;
-
-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 ReadBarriersFields {
-
-    Target target;
-
-    @Setup
-    public void setup() {
-        target = new Target();
-    }
-
-    @Benchmark
-    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
-    public void plainField() {
-        sink(target.plainInt);
-    }
-
-    @Benchmark
-    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
-    public void volatileField() {
-        sink(target.volatileInt);
-    }
-
-    @CompilerControl(CompilerControl.Mode.DONT_INLINE)
-    private void sink(int i) {
-
-    }
-
-    static class Target {
-        int plainInt;
-        volatile int volatileInt;
-    }
-
-    /*
-       i7 4790K, 4.0 Ghz, Linux x86_64, JDK 9 (Shenandoah, 2016-09-05)
-
-            Benchmark                         Mode  Cnt  Score   Error  Units
-
-            # Shenandoah
-            ReadBarriersFields.plainField     avgt   25  3.440 ± 0.019  ns/op
-            ReadBarriersFields.volatileField  avgt   25  3.431 ± 0.006  ns/op
-
-            # G1
-            ReadBarriersFields.plainField     avgt   25  3.149 ± 0.005  ns/op
-            ReadBarriersFields.volatileField  avgt   25  3.147 ± 0.003  ns/op
-
-            # Parallel
-            ReadBarriersFields.plainField     avgt   25  3.149 ± 0.004  ns/op
-            ReadBarriersFields.volatileField  avgt   25  3.152 ± 0.006  ns/op
-
-        The difference is caused by the additional instructions:
-
-            Benchmark                                             Mode  Cnt   Score    Error  Units
-
-            # ------------- Shenandoah
-            ReadBarriersFields.plainField                        avgt   25   3.440 ±  0.014  ns/op
-            ReadBarriersFields.plainField:CPI                    avgt    5   0.380 ±  0.018   #/op  <--- better CPI
-            ReadBarriersFields.plainField:L1-dcache-load-misses  avgt    5   0.018 ±  0.005   #/op
-            ReadBarriersFields.plainField:L1-dcache-loads        avgt    5  15.646 ±  0.548   #/op  <--- more loads
-            ReadBarriersFields.plainField:L1-dcache-stores       avgt    5   7.672 ±  0.292   #/op
-            ReadBarriersFields.plainField:branch-misses          avgt    5   0.008 ±  0.002   #/op
-            ReadBarriersFields.plainField:branches               avgt    5   6.186 ±  0.306   #/op  <--- one more branch
-            ReadBarriersFields.plainField:cycles                 avgt    5  13.866 ±  0.967   #/op
-            ReadBarriersFields.plainField:instructions           avgt    5  36.500 ±  1.875   #/op
-
-            # ------------- G1
-            ReadBarriersFields.plainField                        avgt   25   3.152 ±  0.008  ns/op
-            ReadBarriersFields.plainField:CPI                    avgt    5   0.426 ±  0.017   #/op
-            ReadBarriersFields.plainField:L1-dcache-load-misses  avgt    5   0.019 ±  0.021   #/op
-            ReadBarriersFields.plainField:L1-dcache-loads        avgt    5  12.612 ±  0.146   #/op
-            ReadBarriersFields.plainField:L1-dcache-stores       avgt    5   6.932 ±  0.141   #/op
-            ReadBarriersFields.plainField:branch-misses          avgt    5   0.008 ±  0.002   #/op
-            ReadBarriersFields.plainField:branches               avgt    5   5.226 ±  0.214   #/op
-            ReadBarriersFields.plainField:cycles                 avgt    5  12.794 ±  0.929   #/op
-            ReadBarriersFields.plainField:instructions           avgt    5  30.012 ±  1.198   #/op
-
-            # ------------- Parallel
-            Benchmark                                            Mode  Cnt   Score    Error  Units
-            ReadBarriersFields.plainField                        avgt   25   3.157 ±  0.012  ns/op
-            ReadBarriersFields.plainField:CPI                    avgt    4   0.426 ±  0.027   #/op
-            ReadBarriersFields.plainField:L1-dcache-load-misses  avgt    5   0.020 ±  0.016   #/op
-            ReadBarriersFields.plainField:L1-dcache-loads        avgt    5  12.641 ±  0.446   #/op
-            ReadBarriersFields.plainField:L1-dcache-stores       avgt    5   6.927 ±  0.139   #/op
-            ReadBarriersFields.plainField:branch-misses          avgt    5   0.007 ±  0.002   #/op
-            ReadBarriersFields.plainField:branches               avgt    5   5.212 ±  0.235   #/op
-            ReadBarriersFields.plainField:cycles                 avgt    5  12.754 ±  0.771   #/op
-            ReadBarriersFields.plainField:instructions           avgt    4  29.963 ±  1.944   #/op
-
-        These instructions are the read barriers, plus an explicit null check:
-
-                               [Verified Entry Point]
-              7.25%    7.27%     0x00007fde8d540be0: mov    %eax,-0x14000(%rsp)
-              0.16%    0.06%     0x00007fde8d540be7: push   %rbp
-              0.04%              0x00007fde8d540be8: sub    $0x10,%rsp
-              7.51%    8.68%     0x00007fde8d540bec: mov    -0x8(%rsi),%r10     ; <--- read barrier
-              0.04%              0x00007fde8d540bf0: mov    0xc(%r10),%r10d     ; get field $target
-              0.04%    0.04%     0x00007fde8d540bf4: test   %r10d,%r10d         ; <--- null check $target
-              0.01%           ╭  0x00007fde8d540bf7: je     0x00007fde8d540c18
-              7.36%    8.40%  │  0x00007fde8d540bf9: shl    $0x3,%r10
-              0.19%    0.13%  │  0x00007fde8d540bfd: mov    -0x8(%r10),%r10     ; <--- read barrier
-              1.44%    1.20%  │  0x00007fde8d540c01: mov    0xc(%r10),%edx      ; get field $plainInt
-             23.63%   29.86%  │  0x00007fde8d540c05: xchg   %ax,%ax
-              0.11%    0.10%  │  0x00007fde8d540c07: callq  0x00007fde860c2ce0  ; call sink()
-              7.41%    5.41%  │  0x00007fde8d540c0c: add    $0x10,%rsp
-              0.11%    0.06%  │  0x00007fde8d540c10: pop    %rbp
-                       0.01%  │  0x00007fde8d540c11: test   %eax,0x18d633e9(%rip)
-              7.82%    5.10%  │  0x00007fde8d540c17: retq
-
-         It seems compressed oops are precluding folding the explicit null check. The same run with
-         -XX:-UseCompressedOops:
-
-                               [Verified Entry Point]
-              7.82%    7.02%     0x00007f2ec55430d0: mov    %eax,-0x14000(%rsp)
-              0.04%              0x00007f2ec55430d7: push   %rbp
-              0.65%    0.05%     0x00007f2ec55430d8: sub    $0x10,%rsp
-              6.71%    8.14%     0x00007f2ec55430dc: mov    -0x8(%rsi),%r10    ; <--- read barrier
-                       0.01%     0x00007f2ec55430e0: mov    0x10(%r10),%r10    ; get field $target
-              0.54%    0.65%  ╭  0x00007f2ec55430e4: mov    -0x8(%r10),%r10    ; <--- read barrier    ; implicit exception: dispatches to 0x00007f2ec554310d
-              7.54%    9.11%  │  0x00007f2ec55430e8: mov    0x10(%r10),%edx    ; get field $plainInt
-             20.15%   26.85%  │  0x00007f2ec55430ec: data16 xchg %ax,%ax
-                              │  0x00007f2ec55430ef: callq  0x00007f2ebe0c81e0 ; call sink();
-              7.02%    5.61%  │  0x00007f2ec55430f4: add    $0x10,%rsp
-              0.01%    0.01%  │  0x00007f2ec55430f8: pop    %rbp
-              0.49%    0.71%  │  0x00007f2ec55430f9: test   %eax,0x18ccff01(%rip)
-              7.19%    4.31%  │  0x00007f2ec55430ff: retq
-
-     */
-
-}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/org/openjdk/gcbench/runtime/reads/fields/Plain.java	Thu Dec 01 14:27:24 2016 +0100
@@ -0,0 +1,116 @@
+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;
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/org/openjdk/gcbench/runtime/reads/fields/Volatile.java	Thu Dec 01 14:27:24 2016 +0100
@@ -0,0 +1,116 @@
+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;
+    }
+
+}