RFR: JDK-8277095 : Empty streams create too many objects [v2]
j3graham
duke at openjdk.org
Sat Jul 16 21:47:43 UTC 2022
On Tue, 16 Nov 2021 20:53:26 GMT, kabutz <duke at openjdk.org> wrote:
>> This is a draft proposal for how we could improve stream performance for the case where the streams are empty. Empty collections are common-place. If we iterate over them with an Iterator, we would have to create one small Iterator object (which could often be eliminated) and if it is empty we are done. However, with Streams we first have to build up the entire pipeline, until we realize that there is no work to do. With this example, we change Collection#stream() to first check if the collection is empty, and if it is, we simply return an EmptyStream. We also have EmptyIntStream, EmptyLongStream and EmptyDoubleStream. We have taken great care for these to have the same characteristics and behaviour as the streams returned by Stream.empty(), IntStream.empty(), etc.
>>
>> Some of the JDK tests fail with this, due to ClassCastExceptions (our EmptyStream is not an AbstractPipeline) and AssertionError, since we can call some methods repeatedly on the stream without it failing. On the plus side, creating a complex stream on an empty stream gives us upwards of 50x increase in performance due to a much smaller object allocation rate. This PR includes the code for the change, unit tests and also a JMH benchmark to demonstrate the improvement.
>
> kabutz has updated the pull request incrementally with one additional commit since the last revision:
>
> Refactored empty stream implementations to reduce duplicate code and improved unordered()
> Added StreamSupport.empty for primitive spliterators and use that in Arrays.stream()
src/java.base/share/classes/java/util/stream/StreamSupport.java line 339:
> 337: * @return a new sequential empty {@code IntStream}
> 338: */
> 339: public static IntStream emptyIntStream(Spliterator.OfInt spliterator) {
In the interest of not adding new public APIs, can these be removed in favour of eg, IntStream.empty()? It wouldn’t take the spliterator, but perhaps it isn’t necessary.
-------------
PR: https://git.openjdk.org/jdk/pull/6275
More information about the core-libs-dev
mailing list