In Scala you can use a global ExecutionContext
if you don't need to define your own by importing scala.concurrent.ExecutionContext.Implicits.global
.
My question is why ForkJoinPool
was chosen for this executor instead of ThreadPoolExecutor
.
My understanding is that the fork-join framework is excellent at recursively decomposing problems. You're supposed to write code that breaks a task into halves, so that half can be executed in-thread and the other half can be executed by another thread. This seems like a very particular programming model and not one that would be generally applicable to handling execution of general asynchronous tasks across a wide range of possible applications.
So why was ForkJoinPool
chosen for the default execution context that most people will likely use? Does the work-stealing design result in improved performance even if you don't use the full fork-join paradigm?
I can't speak for the scala designers, but idiomatic use of scala Future
s often involves creation of a lot of very small, short-lived tasks (e.g. every map
call creates a new task) and so the work-stealing design is appropriate.
If you care about these kind of precise details you might prefer to use scalaz-concurrent's Future
, which uses trampolines to avoid creating extra tasks for each map
step and makes execution contexts explicit (and AIUI defaults to a ThreadPoolExecutor
).
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