Hacker News new | ask | show | jobs
by marginalia_nu 961 days ago
Well yeah, this is true for openmp as well.

In my experience, parallel streams rarely deliver a substantial performance boost. There are cases where they do, but it's more the exception than the rule. The overhead from the streams API, along with the synchronization penalties means it mostly only makes sense for coarse grained I/O laden operations.

2 comments

In the entire time I worked at a web shop with a large Java backend I never found the parallelization to be necessary, and in many cases was outright dangerous. We just had it disabled on high-traffic services (thread limit set at 1) to prevent foot injuries.

Don't mean to detract from the point :-). I love how neat and elegant the feature is.

> We just had it disabled on high-traffic services (thread limit set at 1) to prevent foot injuries.

Can you please elaborate?

The default thread pool will use all available cores on the machine. With multiple developers arbitrarily using parallel streams in business logic because it "sounds faster" there is more risk of disrupting concurrent requests.
> The default thread pool will use all available cores on the machine

This is actually a bit of a headache on many-core machines for another reason.

e.g. my production machine has 128 cores, and carelessly parallelizing a memory hungry task (not realizing it will run across 128 threads), risks allocating sevral hundred gigabytes of RAM, and may not even be faster given all the NUMA overhead when thrashing on all cores.

Have to be careful to always down-tune the common pool size to 32 or something.

OpenMP is not a language? You can take any language and add libraries to achieve a specific goal, my point is that Java streams are first-class citizens compared to other matured programming languages that also enable leveraging other aspects of the Java ecosystem without running into the rough edges you will with OpenMP.

Also, that is definitely not the rule? If your problem is parallelizable by nature, parallelism provides massive speedups. Overhead from parallelizing a stream is minimal (effectively nonexistent) now if you leverage Java virtual threads (JDK 21). Additionally, most problems are not parallelizable, yes, but most solutions consist of individual steps and there is a high likelihood that at least one of those steps will benefit from parallelism. Java streams can switch between .parallel() and .sequential() execution on the go. You almost certainly don't want to leverage stream parallelism for most I/O operations, unless you leverage Java's Completeable Futures and Managed Blocking (but any gains here are probably minimal anyways) but the point is that you can leverage them, because streams in Java are a first class citizen.

OpenMP is a compiler flag away.

> Also, that is definitely not the rule? If your problem is parallelizable by nature, parallelism provides massive speedups. Overhead from parallelizing a stream is minimal (effectively nonexistent) now if you leverage Java virtual threads (JDK 21)

This is just not true at all. Not only do virtual threads cope very poorly with I/O other than network I/O, you still get memory barriers. Virtual threads makes the memory overhead lower since you don't need full separate stacks and reduces the cost of spawning new threads, neither of which was ever an issue with streams since they use the common thread pool. Virtual threads don't significantly increase the per-thread performance.

> Not only do virtual threads cope very poorly with I/O other than network I/O, you still get memory barriers.

Which is why I said you probably don't want to use the paradigm I outlined for I/O, but if you did you would want to leverage Java's Managed Blockers and async Completeable Futures for those exact reasons.

> Virtual threads makes the memory overhead lower since you don't need full separate stacks and reduces the cost of spawning new threads, neither of which was ever an issue with streams since they use the common thread pool. Virtual threads don't significantly increase the per-thread performance.

Of course virtual threads don't significantly increase per-thread performance? They make the overhead of spawning multiple threads minimal-to-zero compared to native OS/platform threads, minimizing the cost of jumping from sequential streams to parallel streams. Also, parallel streams don't have to use the global fork join pool, you can use your own fork-join pool? Which is possible in Java, because once again, streams are treated as a first-class citizen and can leverage nearly all other parts of the language efficiently and natively (although I will say Java's verbosity/boilerplateness can suck if you want to leverage your own fork-join pool, but that's widespread complaint of Java not specific to its streams)

>OpenMP is not a language?

Why does it matter that OpenMP is only a standard, rather than a language?

>my point is that Java streams are first-class citizens

They aren't. They were bolted on later and are quite cumbersome.

>without running into the rough edges you will with OpenMP.

I'm pretty sure it is easier to write fast parallel code with OpenMP than with Java streams. In fact, I am always surprised how well OpenMP works, when I get to use it.