0

Suppose I have a naive factorial function:

import java.util.stream.LongStream; public class FactorialTest { static long factorial(long n, boolean parallel) { return (parallel ? LongStream.range(1, n).parallel() : LongStream.range(1, n)) .reduce(1, (l, m) -> l * m); } public static void main(String[] args) { System.out.println(factorial(10, true)); } } 

I have a feeling that multi-threaded reduction is still faster than single-threaded even on a single-logical-core machine. How can I test this with the stream API or work around it?

2
  • 1
    "I have a feeling that multi-threaded reduction is still faster than single-threaded" - don't 'feel', Benchmark! Commented Jul 28, 2014 at 0:34
  • @MitchWheat Exactly. How can I compel multithreaded execution on a single-core machine? That was the original question. Commented Jul 28, 2014 at 0:55

1 Answer 1

5

On JDK 8, parallel streams are by default executed within the common fork-join pool, which is documented on the ForkJoinPool javadoc page. This page documents a system property java.util.concurrent.ForkJoinPool.common.parallelism that you can set to control the number of threads (amount of parallelism) in the common pool.

To benchmark code that takes a relatively small amount of time, I recommend that you use JMH. This is an open-source micro-benchmarking tool that has facilities to avoid most benchmarking pitfalls, such as dead code elimination and JIT warmup times.

Even still, 10! (ten factorial) is only ten multiplies, which will take only a few nanoseconds. Worse, you will overflow a long value at 21! which is still a very short workload. With these short times I suspect that the overhead of setting up a stream -- either serial or parallel -- will dominate the actual computation. But what the heck, go ahead and measure it! You'll probably want to find a heavier workload to benchmark in any case though.

Sign up to request clarification or add additional context in comments.

3 Comments

I've been wanting to ask this for some time: where exactly is it documented that ForkJoin is used by the Streams API at all, nevermind the specific pool instance?
@MarkoTopolnik Deliberately unspecified. (I'll add some hedging to my answer.) In the future it may be possible to run parallel streams on different kinds of thread pools or on things like GPUs, so specifying ForkJoinPool would be premature.
Sure, it shouldn't enter the specification, but it could stand as an implementation note. The note could also include the fact that the common pool is being used (this, too, does not follow from what is being said on the FJP javadoc page). For many practical considerations this is actually vital information.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.