On 02/19/2015 07:26 PM, Aleksey Shipilev wrote:
However, if you do the actual benchmark that compares explicit NP checks
vs implicit NP checks (that benchmark is very tricky to get right):
  http://cr.openjdk.java.net/~shade/scratch/NullCheckPollution.java

Benchmark         (count)  (pollute)  Mode  Cnt  Score   Error  Units
NCP.testExplicit   100000      false  avgt   50  1.813 ± 0.004  ns/op
NCP.testExplicit   100000       true  avgt   50  1.891 ± 0.029  ns/op
NCP.testImplicit   100000      false  avgt   50  1.812 ± 0.003  ns/op
NCP.testImplicit   100000       true  avgt   50  1.811 ± 0.001  ns/op

There, testExplicit with pollution is the only one that has explicit
test+branch. The difference is minuscule (< 1/3 of CPU cycle), and I
would choose not to care, even for JDK code.

Hi Aleksey,

Good to know that requireNonNull is mostly not an issue after all. Thanks for taking time to create a real microbenchmark for it. I too have tried, but couldn't get it to show any difference between polluted and non-polluted test case (probably because I didn't use CompilerControl.Mode.DONT_INLINE ). Running your test on my hw (i7-2600K CPU) gives a little different result though (this is with 64bit JDK 8u20):


Benchmark (count) (pollute) Mode Samples Score Error Units j.t.NullCheckPollution.testExplicit 100000 false avgt 50 1.908 ± 0.052 ns/op j.t.NullCheckPollution.testExplicit 100000 true avgt 50 2.291 ± 0.036 ns/op j.t.NullCheckPollution.testImplicit 100000 false avgt 50 1.906 ± 0.048 ns/op j.t.NullCheckPollution.testImplicit 100000 true avgt 50 1.865 ± 0.025 ns/op


...and with recent build of JDK9:


Benchmark (count) (pollute) Mode Samples Score Error Units j.t.NullCheckPollution.testExplicit 100000 false avgt 50 1.871 ± 0.056 ns/op j.t.NullCheckPollution.testExplicit 100000 true avgt 50 2.278 ± 0.022 ns/op j.t.NullCheckPollution.testImplicit 100000 false avgt 50 1.867 ± 0.025 ns/op j.t.NullCheckPollution.testImplicit 100000 true avgt 50 1.899 ± 0.058 ns/op


Perhaps my CPU is too old (4 years!) to be smart enough (like yours)? I checked on a Sparc-T5 CPU (JDK 8u40b23) too:


Benchmark (count) (pollute) Mode Samples Score Error Units j.t.NullCheckPollution.testExplicit 100000 false avgt 50 3.089 ± 0.062 ns/op j.t.NullCheckPollution.testExplicit 100000 true avgt 50 3.596 ± 0.090 ns/op j.t.NullCheckPollution.testImplicit 100000 false avgt 50 3.100 ± 0.060 ns/op j.t.NullCheckPollution.testImplicit 100000 true avgt 50 3.211 ± 0.204 ns/op


...but this only happens if the method doing explicit null check is not inlined into the test method. If I change DONT_INLINE -> INLINE, the difference is hidden within noise (i7-2600K, JDK9):


Benchmark (count) (pollute) Mode Samples Score Error Units j.t.NullCheckPollution.testExplicit 100000 false avgt 50 0.456 ± 0.005 ns/op j.t.NullCheckPollution.testExplicit 100000 true avgt 50 0.482 ± 0.024 ns/op j.t.NullCheckPollution.testImplicit 100000 false avgt 50 0.457 ± 0.006 ns/op j.t.NullCheckPollution.testImplicit 100000 true avgt 50 0.456 ± 0.004 ns/op


So we hope for Objects.requireNonNull to be inlined most of the times. It would be nice if @ForceInline annotation was accessible outside java.lang.invoke package, so methods like requireNonNull could benefit from it too. With modules, such platform annotations could be made public and put into a package (java.lang.internal) that is not exported to the world.


Regards, Peter



Reply via email to