Akka 2.x requires many commands to reference an ActorSystem
. So, to create an instance of an actor MyActor
you might say:
val system = ActorSystem()
val myActor = system.actorOf(Props[MyActor])
Because of the frequent need for an ActorSystem
: many code examples omit the creation from the code and assume that the reader knows where a system
variable has come from.
If your code produces actors in different places, you could duplicate this code, possibly creating additional ActorSystem
instances, or you could try to share the same ActorSystem
instance by referring to some global or by passing the ActorSystem
around.
The Akka documentation provides a general overview of systems of actors under the heading 'Actor Systems', and there is documentation of the ActorSystem
class. But neither of these help a great deal in explaining why a user of Akka can't just rely on Akka to manage this under-the-hood.
Question(s)
What are the implications of sharing the same
ActorSystem
object or creating a new one each time?What are the best practices here? Passing around an
ActorSystem
all the time seems surprisingly heavy-handed.Some examples give the
ActorSystem
a name:ActorSystem("MySystem")
others just callActorSystem()
. What difference does this make, and what if you use the same name twice?Does
akka-testkit
require that you share a commonActorSystem
with the one you pass to theTestKit
constructor?
Creating an ActorSystem is very expensive, so you want to avoid creating a new one each time you need it. Also your actors should run in the same ActorSystem, unless there is a good reason for them not to. The name of the ActorSystem is also part the the path to the actors that run in it. E.g. if you create an actor in a system named
MySystem
it will have a path likeakka://MySystem/user/$a
. If you are in an actor context, you always have a reference to the ActorSystem. In an Actor you can callcontext.system
. I don't know what akka-testkit expects, but you could take a look at the akka tests.So to sum it up, you should always use the same system, unless there is a good reason not to do so.
Here are some materials which might be helpful to understand "Why does document always suggest to use one ActorSystem for one logical application" :
The heaviest part of an ActorSystem is the dispatcher. Each ActorSystem has at least one. The dispatcher is the engine that makes the actors running. In order to make running, it needs threads (usually got from a thread pool). The default dispatcher uses a fork-join thread pool with at least 8 threads.
There are shared facilities, like the guardian actors, the event stream, the scheduler, etc. Some of them are in user space, some are internal. All of them need to be created and started.
One ActorSystem with one thread pool configures to the numbers of cores should give the best results in most cases.
Here document mentions logical application, I prefer to consider blocking or non-blocking application. According to dispatcher's configuration, one ActorSystem is for one configuration. If the application is for the same logics, one ActorSystem should be enough.
Here is a discussion , if you have time, you can read it. They discuss a lot, ActorSystem, local or remote, etc.