Reputation: 11508
How does the execution context from
import scala.concurrent.ExecutionContext.Implicits.global
differ from Play's execution contexts:
import play.core.Execution.Implicits.{internalContext, defaultContext}
Upvotes: 35
Views: 10244
Reputation: 1308
PRELUDE: This question is from 6 years ago, since then many things have changed. I know this is not an answer to the original question, but I was fooled more than 1 day with the same confusion that the original question states; so I decided to share my research results with the community.
The latest update reagrding ExecutionContext, which perfectly applies to Play 2.8.15 is as follows. The Play 2.6 migration guide states:
The play.api.libs.concurrent.Execution class has been deprecated, as it was using global mutable state under the hood to pull the “current” application’s ExecutionContext. If you want to specify the implicit behavior that you had previously, then you should pass in the execution context implicitly in the constructor.
So you cannot use play.api.libs.concurrent.Execution.Implicits.defaultContext
anymore. The no-configuration, out-of-the-box practice is to provide an implicit value of type scala.concurrent.ExecutionContext
for the controller, something like:
import scala.concurrent.ExecutionContext
@Singleton
class AsyncController @Inject()(cc: ControllerComponents, actorSystem: ActorSystem)(implicit exec: ExecutionContext) extends AbstractController(cc)
This means that none of the above answers hold, also the question itself is not relevant anymore, since play.core.Execution.Implicits.defaultContext
is not available anymore.
Upvotes: 2
Reputation: 772
They are the same and point out to the default dispatcher of the underlying actor system in your Play or Akka or combined application.
##Default Play's Context
play.api.libs.concurrent.Execution.Implicits.defaultContext
##Play's Internal Context
play.core.Execution.Implicits.internalContext
##Guice's EC Injected
class ClassA @Inject()(config: Configuration)
(implicit ec: ExecutionContext) {
...
}
But this is different:
scala.concurrent.ExecutionContext.Implicits.global
Also DB drivers, e.g. if you use slick, may come up with their own Execution Context. Anyway,
scala.concurrent.ExecutionContext.Implicits.global
when you are using play or akka framework, in this way you may use more threads than optimum during high load so the performance may decrease.scala.concurrent.ExecutionContext.Implicits.global
when you have no other executor running in your app. Don’t worry this is safe then.Await
for a futureapplication.conf
Upvotes: 13
Reputation: 55569
They are very different.
In Play 2.3.x and prior, play.core.Execution.Implicits.internalContext
is a ForkJoinPool
with fixed constraints on size, used internally by Play. You should never use it for your application code. From the docs:
Play Internal Thread Pool - This is used internally by Play. No application code should ever be executed by a thread in this thread pool, and no blocking should ever be done in this thread pool. Its size can be configured by setting internal-threadpool-size in application.conf, and it defaults to the number of available processors.
Instead, you would use play.api.libs.concurrent.Execution.Implicits.defaultContext
, which uses an ActorSystem
.
In 2.4.x, they both use the same ActorSystem
. This means that Akka will distribute work among its own pool of threads, but in a way that is invisible to you (other than configuration). Several Akka actors can share the same thread.
scala.concurrent.ExecutionContext.Implicits.global
is an ExecutionContext
defined in the Scala standard library. It is a special ForkJoinPool
that using the blocking
method to handle potentially blocking code in order to spawn new threads in the pool. You really shouldn't use this in a Play application, as Play will have no control over it. It also has the potential to spawn a lot of threads and use a ton of memory, if you're not careful.
I've written more about scala.concurrent.ExecutionContext.Implicits.global
in this answer.
Upvotes: 48