I am investigating some performance issues in an app using ForkJoinPool. We've been at it with Dynatrace and there are indications of some blocking operations which last way too long. I cannot find enough information in FJP docs or elsewhere about how to configure and monitor our ForkJoinPools.
What does parallelism mean in the context of ForkJoinPools, and what are the guidelines/best practice for which values to chose for different thread pools (blocking/non-blocking)?
How can I monitor and tune my ForkJoinPool? We are using ForkJoinPool.toString() which gives some counters, but I cannot find enough information in the javadoc on how to use this stats for tuning. getStealCount() is described as "....should be high enough to keep threads busy, but low enough to avoid overhead and contention accross threads", which does not really help.
Example of a toString()
[Running, parallelism = 48, size = 47, active = 0, running = 0, steals
= 33195, tasks = 0, submissions = 0]
ForkJoinPool class is an extension of the AbstractExecutorService class, and it implements the work-stealing algorithm (i.e., worker threads that run out of things to do can steal tasks from other threads that are still busy) of fork/join framework and can execute ForkJoinTask processes.
To arrange the same value as is used by default for the common pool, use 256 plus the parallelism level. (By default, the common pool allows a maximum of 256 spare threads.)
A ForkJoinPool is constructed with a given target parallelism level; by default, equal to the number of available processors. The pool attempts to maintain enough active (or available) threads by dynamically adding, suspending, or resuming internal worker threads, even if some tasks are stalled waiting to join others.
The fork/join framework is an implementation of the ExecutorService interface that helps you take advantage of multiple processors. It is designed for work that can be broken into smaller pieces recursively. The goal is to use all the available processing power to enhance the performance of your application.
To the best of my knowledge, there is no way to tune this "framework.' Configuration is limited to Parallelism, Thread Factory, Exception Handling and spare threads (see below in parallelism.)
I wrote a critique about the F/J code back in 2011. I upgraded the critique several times and no longer waste my time doing so.
Steal count is totally worthless.
There are no stats on each thread, therefore, active, running, tasks, etc. give you no knowledge about what is going on inside the framework. Most of these "monitors" were added as an afterthought years after the original Java7 debut. For instance, for each thread, knowing total compute() methods processed, total waits, etc. would give you an idea of how each thread is performing. However, since the framework adds/deletes threads (see below in parallelism) this can never happen. Having a total overall count of any of these monitors doesn’t tell you anything useful.
join() of course, still has severe problems with blocking (stalling.) If you can use the CountedCompleter Class, you are better off.
Parallelism means the number of initial threads. The framework exceeds this number when threads block up to a maximum (java.util.concurrent.ForkJoinPool.common.maximumSpares (this may not be available in Java8 unless it was backported)). The framework adds/deletes threads according to internal rules (you need to look at the code yourself since it is release dependent.) See also Interface ForkJoinPool.ManagedBlocker and the code to support it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With