On Sat, 6 Nov 2021 22:03:26 GMT, Pavel Rappo <pra...@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. > > src/java.base/share/classes/java/util/Collection.java line 743: > >> 741: */ >> 742: default Stream<E> stream() { >> 743: if (isEmpty()) return Stream.empty(); > > The net effect of this change might depend on your workload. If you call > stream() on empty collections that have cheap isEmpty(), this change will > likely improve performance and reduce waste. However, this same change might > do the opposite if some of your collections aren't empty or have costly > isEmpty(). It would be good to have benchmarks for different workloads. wouldn't this make streams no longer lazy if the collection is empty? List<String> list = new ArrayList<>(); Stream<String> stream = list.stream(); list.addAll(List.of("one", "two", "three")); stream.forEach(System.out::println); // prints one two three ------------- PR: https://git.openjdk.java.net/jdk/pull/6275