[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