Mercurial > hg > gc-bench
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; + } + +}