RFR (S) 8073479: Replace obj.getClass hacks with Objects.requireNonNull
Peter Levart
peter.levart at gmail.com
Fri Feb 20 12:48:07 UTC 2015
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
More information about the core-libs-dev
mailing list