bartull bartull - 2 months ago 13
Scala Question

Does Akka's fork-join-executor make use of scala.concurrent.blocking?

I know that scala.concurrent.blocking is a hint for ExecutionContext that a piece of code performs some long operation / blocks on some IO. ExecutionContext can, but does not have to, make use of this "hint".

As described here:
scala.concurrent.blocking - what does it actually do?

http://www.cakesolutions.net/teamblogs/demystifying-the-blocking-construct-in-scala-futures

scala.concurrent.ExecutionContext.Implicits.global is a ForkJoinPool, which spawns a new thread for a code wrapped in scala.concurrent.blocking.

What about Akka's fork-join-executor. Does it also make use of scala.concurrent.blocking in any way?

m-z m-z
Answer

Yes, it does!

It's easy enough to figure this out by searching for BlockContext. For Akka, that leads us here, and if you follow the threads in the code and documentation, you can confirm it.

This is also easy enough to test on our own. We can make a new ActorSystem without any configured dispatchers (so it will use the default fork-join-executor), then use its dispatcher as our ExecutionContext.

import akka.actor._
import scala.concurrent._

implicit val ec = ActorSystem("test").dispatcher

First, without blocking you will notice that several futures start right away, but not all of them. The another batch will start as the first batch completes. Clearly, the default pool reaches starvation:

(0 to 100) foreach { n =>
    Future {
        println("starting Future: " + n)
        Thread.sleep(3000)
        println("ending Future: " + n)
    }
}

Then, with blocking all of the futures should execute almost immediately, as opposed to the previous example:

(0 to 100) foreach { n =>
    Future {
        println("starting Future: " + n)
        blocking(Thread.sleep(3000))
        println("ending Future: " + n)
    }
}