Should I Always Use a Parallel Stream When Possible

Should I always use a parallel stream when possible?

A parallel stream has a much higher overhead compared to a sequential one. Coordinating the threads takes a significant amount of time. I would use sequential streams by default and only consider parallel ones if

  • I have a massive amount of items to process (or the processing of each item takes time and is parallelizable)

  • I have a performance problem in the first place

  • I don't already run the process in a multi-thread environment (for example: in a web container, if I already have many requests to process in parallel, adding an additional layer of parallelism inside each request could have more negative than positive effects)

In your example, the performance will anyway be driven by the synchronized access to System.out.println(), and making this process parallel will have no effect, or even a negative one.

Moreover, remember that parallel streams don't magically solve all the synchronization problems. If a shared resource is used by the predicates and functions used in the process, you'll have to make sure that everything is thread-safe. In particular, side effects are things you really have to worry about if you go parallel.

In any case, measure, don't guess! Only a measurement will tell you if the parallelism is worth it or not.

How large should my list of objects be to warrant the use of java 8's parallelStream?

According to this and depending on the operation it would require at least 10_000, but not elements; instead N * Q where N = number of elements and Q = cost per element.

But this is a general formula you push against, without measuring this is close to impossible to say (read guess here); proper tests will prove you wrong or right.

For some simple operations, it is almost never the case when you would actually need parallel processing for the purpose of speed-up.

Some other things to mention here, is that this heavily depends on the source - how easy it is to split. Anything array-based or index-based are easy to split (and fast), but a Queue or lines from a File do not, so you will probably lose more time splitting rather than computing, unless, of course, there are enough elements to cover for this. And enough is something you actually measure.

In what application niche is parallelStream from Java useful?

A similar question is asked in Should I always use a parallel stream when possible? Note the second answer is given by Brian Goetz, a Java language architect at Oracle who was involved in the design of the Stream API, so his answer may be considered authoritative.

Top answers are quick to point out that parallel streams include additional overhead necessary for coordination and thus will only increase performance in scenarios where the amount of individual processing per stream is significant enough that the gain from parallel processing overcomes that initial overhead.

Unsurprisingly, as with any question of performance, the advice is to measure rather than guess. Start with a sequential stream, and if you have a large number of elements each requiring complex computation, measure the performance difference of switching to parallel streams.

Additional guidelines, such as those listed in the OP, may be helpful; but people are notoriously bad at identifying performance bottlenecks, so any guidelines are likely to fail eventually in the face of actual measurements.

Does a good use case exist for skip() on parallel streams?

The choice of sequential vs parallel is simply one of execution strategy. The option for parallelism exists so that, if the specifics of the problem (problem size, choice of stream operations, computational work per element, available processors, memory bandwidth, etc) permit, then a performance benefit may be gained by going parallel. Not all combinations of these specifics will admit a performance benefit (and some may even garner a penalty), so we leave it to the user to separately specify the operations from the execution strategy.

For operations like skip() or limit(), which are intrinsically tied to encounter order, it is indeed hard to extract a lot of parallelism, but it is possible; this generally occurs when the computational work per element (often called 'Q') is very high.

Such cases are probably rare (which might be your point); this doesn't make the combination of operation and execution mode "useless", simply of limited usefulness. But one doesn't design a API with multiple dimensions (operations, execution modes) based on the combinations that one can imagine is useful; assuming each combination has a sensible semantics (which it does in this case), it is best to allow all operations in all modes and let the users decide which is useful for them.

Why does stream parallel() not use all available threads?

Since the Stream implementation’s use of the Fork/Join pool is an implementation detail, the trick to force it to use a different Fork/Join pool is undocumented as well and seems to work by accident, i.e. there’s a hardcoded constant determining the actual parallelism, depending on the default pool’s parallelism. So using a different pool was not foreseen, originally.

However, it has been recognized that using a different pool with an inappropriate target parallelism is a bug, even if this trick is not documented, see JDK-8190974.

It has been fixed in Java 10 and backported to Java 8, update 222.

So a simple solution world be updating the Java version.

You may also change the default pool’s parallelism, e.g.

System.setProperty("java.util.concurrent.ForkJoinPool.common.parallelism", "100");

before doing any Fork/Join activity.

But this may have unintended effects on other parallel operations.



Related Topics



Leave a reply



Submit