[PATCH] Collectors.counting() does unnecessary boxing on every accumulation
Tagir F. Valeev
amaembo at gmail.com
Thu Sep 17 09:33:27 UTC 2015
Hello!
Thank you very much!
With best regards,
Tagir Valeev.
PS> Hi Tagir,
PS> Thanks, looks good.
PS> I created:
PS> https://bugs.openjdk.java.net/browse/JDK-8136686
PS> and i also included an update to a test.
PS> Assuming no further review comments i will commit tomorrow.
PS> Paul.
PS> diff -r 4be07e0eb9b6
PS> test/java/util/stream/test/org/openjdk/tests/java/util/stream/CountTest.java
PS> ---
PS> a/test/java/util/stream/test/org/openjdk/tests/java/util/stream/CountTest.java Thu Sep 17 10:37:39 2015 +0800
PS> +++
PS> b/test/java/util/stream/test/org/openjdk/tests/java/util/stream/CountTest.java Thu Sep 17 11:21:16 2015 +0200
PS> @@ -31,6 +31,7 @@
PS> import java.util.HashSet;
PS> import java.util.concurrent.atomic.AtomicInteger;
PS> +import java.util.stream.Collectors;
PS> import java.util.stream.DoubleStream;
PS> import java.util.stream.DoubleStreamTestDataProvider;
PS> import java.util.stream.IntStream;
PS> @@ -61,6 +62,12 @@
PS> expectedResult(expectedCount).
PS> exercise();
PS> + // Test counting collector
PS> + withData(data).
PS> + terminal(s -> s, s ->
PS> s.collect(Collectors.counting())).
PS> + expectedResult(expectedCount).
PS> + exercise();
PS> +
PS> // Test with stateful distinct op that is a barrier or lazy
PS> // depending if source is not already distinct and encounter order is
PS> // preserved or not
PS> On 17 Sep 2015, at 08:02, Tagir F. Valeev <amaembo at gmail.com> wrote:
>> Hello!
>>
>> Could you please consider the following very simple patch to
>> Collectors.counting() implementation?
>>
>> diff --git a/src/java.base/share/classes/java/util/stream/Collectors.java b/src/java.base/share/classes/java/util/stream/Collectors.java
>> --- a/src/java.base/share/classes/java/util/stream/Collectors.java
>> +++ b/src/java.base/share/classes/java/util/stream/Collectors.java
>> @@ -504,7 +504,7 @@
>> */
>> public static <T> Collector<T, ?, Long>
>> counting() {
>> - return reducing(0L, e -> 1L, Long::sum);
>> + return summingLong(e -> 1L);
>> }
>>
>> /**
>>
>> ===== END-OF-PATCH =====
>>
>> Current implementation uses reducing collector which is not
>> primitive-specialized, thus on every accumulation event the current
>> Long value is unboxed, then boxed again (inside one-element Object[]
>> array created in "reducing"). As this collector is intended for
>> downstream use, these boxes are usually stored as map values for
>> different keys, thus JIT-compiler has practically no chance to
>> optimize out these operations. In contrast summingLong is more
>> performant as it uses the primitive long[] one-element array and
>> modifies it in-place.
>>
>> Though it's quite obvious that this change should improve the
>> performance, I did some simple benchmark here:
>> https://gist.github.com/amaembo/6d9c0e74fec99c665620
>> Using summingLong can be up to 30% faster.
>>
>> With best regards,
>> Tagir Valeev.
>>
More information about the core-libs-dev
mailing list