RFR: 8274715: Implement forEach in Collections.CopiesList
Martin Buchholz
martin at openjdk.java.net
Mon Oct 4 16:54:10 UTC 2021
On Thu, 11 Feb 2021 13:28:49 GMT, Сергей Цыпанов <github.com+10835776+stsypanov at openjdk.org> wrote:
> Originally was proposed by Zheka Kozlov here: http://mail.openjdk.java.net/pipermail/core-libs-dev/2018-December/057192.html
>
> Just a tiny optimization: we can use for-i loop instead of `Iterable.forEach()` which is relying on iterator.
>
> Simple benchmark demonstrates slight improvement:
>
> @State(Scope.Thread)
> @BenchmarkMode(Mode.AverageTime)
> @OutputTimeUnit(TimeUnit.NANOSECONDS)
> public class NCopiesBenchmarks {
> @Param({"10", "50", "100"})
> int size;
>
> private List<Object> list;
>
> @Setup
> public void prepare() {
> list = Collections.nCopies(size, new Object());
> }
>
> @Benchmark
> public void forEach(Blackhole bh) {
> list.forEach(bh::consume);
> }
> }
>
>
>
> before
>
> Benchmark (size) Mode Cnt Score Error Units
> NCopiesBenchmarks.forEach 10 avgt 50 40.737 ± 1.854 ns/op
> NCopiesBenchmarks.forEach:·gc.alloc.rate 10 avgt 50 0.001 ± 0.001 MB/sec
> NCopiesBenchmarks.forEach:·gc.alloc.rate.norm 10 avgt 50 ≈ 10⁻⁴ B/op
> NCopiesBenchmarks.forEach:·gc.count 10 avgt 50 ≈ 0 counts
> NCopiesBenchmarks.forEach 50 avgt 50 213.324 ± 3.784 ns/op
> NCopiesBenchmarks.forEach:·gc.alloc.rate 50 avgt 50 0.001 ± 0.001 MB/sec
> NCopiesBenchmarks.forEach:·gc.alloc.rate.norm 50 avgt 50 ≈ 10⁻³ B/op
> NCopiesBenchmarks.forEach:·gc.count 50 avgt 50 ≈ 0 counts
> NCopiesBenchmarks.forEach 100 avgt 50 443.171 ± 17.919 ns/op
> NCopiesBenchmarks.forEach:·gc.alloc.rate 100 avgt 50 0.001 ± 0.001 MB/sec
> NCopiesBenchmarks.forEach:·gc.alloc.rate.norm 100 avgt 50 0.001 ± 0.001 B/op
> NCopiesBenchmarks.forEach:·gc.count 100 avgt 50 ≈ 0 counts
>
> after
>
> Benchmark (size) Mode Cnt Score Error Units
> NCopiesBenchmarks.forEach 10 avgt 50 36.838 ± 0.065 ns/op
> NCopiesBenchmarks.forEach:·gc.alloc.rate 10 avgt 50 0.001 ± 0.001 MB/sec
> NCopiesBenchmarks.forEach:·gc.alloc.rate.norm 10 avgt 50 ≈ 10⁻⁴ B/op
> NCopiesBenchmarks.forEach:·gc.count 10 avgt 50 ≈ 0 counts
> NCopiesBenchmarks.forEach 50 avgt 50 191.173 ± 0.570 ns/op
> NCopiesBenchmarks.forEach:·gc.alloc.rate 50 avgt 50 0.001 ± 0.001 MB/sec
> NCopiesBenchmarks.forEach:·gc.alloc.rate.norm 50 avgt 50 ≈ 10⁻⁴ B/op
> NCopiesBenchmarks.forEach:·gc.count 50 avgt 50 ≈ 0 counts
> NCopiesBenchmarks.forEach 100 avgt 50 376.675 ± 2.476 ns/op
> NCopiesBenchmarks.forEach:·gc.alloc.rate 100 avgt 50 0.001 ± 0.001 MB/sec
> NCopiesBenchmarks.forEach:·gc.alloc.rate.norm 100 avgt 50 0.001 ± 0.001 B/op
> NCopiesBenchmarks.forEach:·gc.count 100 avgt 50 ≈ 0 counts
Core collection classes should have optimized versions of forEach, so this is a good change in principle. Although CopiesList.forEach is unlikely to be performance critical.
I implemented many similar optimizations for core collection classes in past years.
Many of them are benchmarked in test/jdk/java/util/Collection/IteratorMicroBenchmark.java
That was written pre-JMH.
I see a JMH benchmark was written, but it is not part of the commit.
There are a number of unrelated changes in this commit that look like they were suggested by a lint-like tool. Such changes are good, but they belong in a separate cleanup commit applied across large portions of the jdk sources.
I would not use "var" here - more readable with concrete types.
Similarly, I prefer not using diamond for
return new Enumeration<T>() {
-------------
Changes requested by martin (Reviewer).
PR: https://git.openjdk.java.net/jdk/pull/2524
More information about the core-libs-dev
mailing list