We observed a strange behavior when we tried to start a number of futures from within an actor\'s receive method. If we use our configured dispatchers as ExecutionContext,
After some research I found out that the Dispatcher
class implememts akka.dispatch.BatchingExecutor
. For performance reasons, this class checks which tasks should be batched on the same thread. Future.map
internally creates a scala.concurrent.OnCompleteRunnable
which is batched in the BatchingExecutor
.
This seems to be reasonable for map()
/ flatMap()
where one task generates one subsequent task, but not for explicit new Futures which are used to fork work.
Internally, Future.apply
is implemented by Future.successful().map
and is thus batched. My workaround is now to create futures in a different way:
object MyFuture {
def apply[T](body: =>T)(implicit executor: ExecutionContext): Future[T] = {
val promise = Promise[T]()
class FuturesStarter extends Runnable {
override def run(): Unit = {
promise.complete(Try(body))
}
}
executor.execute(new FuturesStarter)
promise.future
}
}
The FutureStarter
-Runnables are not batched and thus run in parallel.
Can anybody confirm that this solution is okay?
Are there better ways to resolve this issue?
Is the current implementation of Future
/ BatchingExecutor
wanted, or is it a bug?