RFR: 8312424: 80% throughput decrease in Arrays.hashCode(Object[]) after JDK-8312164
Jorn Vernee
jvernee at openjdk.org
Thu Jul 20 14:44:42 UTC 2023
On Thu, 20 Jul 2023 01:11:43 GMT, Glavo <duke at openjdk.org> wrote:
> The changes to `Arrays.hashCode(Object[])` in JDK-8312164 caused its performance is reduced by about 80%.
>
> This PR reverts this change.
With a size of `1`, the polymorphic version is not really polymorphic. This seems to be about profile pollution inside `Objects.hashCode(Object)`. But, the same pollution can happen for `Arrays.hashCode(Object[])` as well, unless an application only ever calls this method with arrays with the same element type (seems unlikely).
To create a representative 'polluted' benchmark, you should create at least 2 other arrays that hold instances of another type than `Integer`, and then call `Arrays.hashCode` a bunch (like 10K times) in the setup method. [1]. Note how the polluted case is exactly the same with the old code:
Objects.hashCode(Object)
Benchmark (pollute) (size) Mode Cnt Score Error Units
ArraysHashCode.objects true 1 avgt 15 3.053 ± 0.011 ns/op
ArraysHashCode.objects true 10 avgt 15 26.955 ± 0.192 ns/op
ArraysHashCode.objects true 100 avgt 15 269.441 ± 1.788 ns/op
ArraysHashCode.objects true 10000 avgt 15 26419.822 ± 56.444 ns/op
ArraysHashCode.objects false 1 avgt 15 3.049 ± 0.007 ns/op
ArraysHashCode.objects false 10 avgt 15 26.797 ± 0.040 ns/op
ArraysHashCode.objects false 100 avgt 15 268.127 ± 0.351 ns/op
ArraysHashCode.objects false 10000 avgt 15 26446.978 ± 66.340 ns/op
(element == null ? 0 : element.hashCode())
Benchmark (pollute) (size) Mode Cnt Score Error Units
ArraysHashCode.objects true 1 avgt 15 3.056 ± 0.015 ns/op
ArraysHashCode.objects true 10 avgt 15 26.840 ± 0.081 ns/op
ArraysHashCode.objects true 100 avgt 15 268.204 ± 0.462 ns/op
ArraysHashCode.objects true 10000 avgt 15 26410.336 ± 77.897 ns/op
ArraysHashCode.objects false 1 avgt 15 0.818 ± 0.001 ns/op
ArraysHashCode.objects false 10 avgt 15 5.130 ± 0.013 ns/op
ArraysHashCode.objects false 100 avgt 15 58.394 ± 0.508 ns/op
ArraysHashCode.objects false 10000 avgt 15 6274.471 ± 427.928 ns/op
If you look at `PrintInlining` output for the `(element == null ? 0 : element.hashCode())` version of the code:
Non-polluted:
@ 1 java.util.Arrays::hashCode (56 bytes) inline (hot)
@ 43 java.lang.Integer::hashCode (8 bytes) inline (hot)
-> TypeProfile (15360/15360 counts) = java/lang/Integer
@ 4 java.lang.Integer::hashCode (2 bytes) inline (hot)
Polluted:
@ 1 java.util.Arrays::hashCode (56 bytes) inline (hot)
@ 43 java.lang.Object::hashCode (0 bytes) (intrinsic, virtual)
i.e. `Arrays::hashCode(Object[])` is still susceptible to pollution, and I don't really think that the benchmark you've added in this PR is representative of a real world scenario since it only uses one element type. I don't think using `Objects.hashCode` is really that much of a problem here. Though, I'll grant that it at least has an observable difference.
[1]: https://github.com/openjdk/jdk/compare/master...JornVernee:jdk:PollutedBenchmark
-------------
PR Comment: https://git.openjdk.org/jdk/pull/14944#issuecomment-1644050455
More information about the core-libs-dev
mailing list