[PATCH] Collectors.counting() does unnecessary boxing on every accumulation

Paul Sandoz paul.sandoz at oracle.com
Thu Sep 17 09:21:46 UTC 2015


Hi Tagir,

Thanks, looks good.

I created:

  https://bugs.openjdk.java.net/browse/JDK-8136686

and i also included an update to a test.

Assuming no further review comments i will commit tomorrow.

Paul.

diff -r 4be07e0eb9b6 test/java/util/stream/test/org/openjdk/tests/java/util/stream/CountTest.java
--- a/test/java/util/stream/test/org/openjdk/tests/java/util/stream/CountTest.java	Thu Sep 17 10:37:39 2015 +0800
+++ b/test/java/util/stream/test/org/openjdk/tests/java/util/stream/CountTest.java	Thu Sep 17 11:21:16 2015 +0200
@@ -31,6 +31,7 @@

 import java.util.HashSet;
 import java.util.concurrent.atomic.AtomicInteger;
+import java.util.stream.Collectors;
 import java.util.stream.DoubleStream;
 import java.util.stream.DoubleStreamTestDataProvider;
 import java.util.stream.IntStream;
@@ -61,6 +62,12 @@
                 expectedResult(expectedCount).
                 exercise();

+        // Test counting collector
+        withData(data).
+                terminal(s -> s, s -> s.collect(Collectors.counting())).
+                expectedResult(expectedCount).
+                exercise();
+
         // Test with stateful distinct op that is a barrier or lazy
         // depending if source is not already distinct and encounter order is
         // preserved or not


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