First things first can you make enough space for the actors. You might be
surprised by what you can do on a modern machine :) Of course this is a
non-answer. But this does force you to answer capacity planning questions
like:
i) How much state will each of these actors have i.e. how much memory
will each actor consume?
ii) How many actors can you potentially have in the system?
iii) How often do these actors receive msgs?
This exercise will lead to an answer of the form : "I have enough memory to
represent X amount of actors but I need Y memory that I can dedicate to
these specific actors". If Y > X then your problem is solved. If it's not
then the exercise really boils down to how do I keep around more state than
can fit in memory. I see a few options:
1) You can turn your individual actors to "fat actors". You can make each
of them responsible for a certain % of leaf actors. You might get
significant savings from the aggregation of state (think one giant map vs
many small maps). Sometimes you might not. If you do get enough savings
where Y is not more than X, then you are in luck. Cons include not writing
things in an "object oriented" manner. You just figure out which ShardActor
to msg to when you need to reach a particular IndividualActor and it does
everything. Sharding logic is up to you and routers might assist. You can
keep a dedicated executionContext for these shard actors so you can isolate
and analyze their performance and parallelize appropriately.
2) If there is no way to fit all actors in memory using (1) then you have
to have a mechanism of deflating them and then inflating them again. No
magic here. This is like virtual memory - when you don't have enough memory
page out to disk. This ties to how you populate the state in each actor to
begin with. You could use files, databases, Akka persistence etc. What you
can do then is have one or more shard actors that control when actors are
serialized/deserialized. Pseudo-code:
class ShardActor extends actor {
state...
def receive = {
case Msg(Id, payload) => {
if (activeDirectory contains Id) {
actor = activeDirectory get Id
Cancel any timer msg that requires us to shutdown this actor since
it is active.
actor.tell(payload, sender) // In case you want to preseve the
original sender
Start timer to send yourself a msg to ask this actor to shutdown.
} else {
create RealActor with id Id. The RealActor should be able to
inflate it's state from a database, filesystem or whatever.
actor.tell(payload, sender)
Start timer to send yourself a msg to ask this actor to shutdown.
}
}
case InactiveActorTimerMsg(Id) => {
// Timer for this actor has hit. It's been inactive for too long.
Send a msg to the actor to serialize itself and shut itself down.
actorRef = Directory get Id // Assume it's there. Use pattern
matching (Some, None) in real life etc etc.
Remove actorRef from activeDirectory.
actorRef ! SerializeAndShutYourSelfDown
// We assume that if the child actor cannot serialize itself, there
will be an exception
// and the ShardActor will handle it through its supervision strategy.
}
}
On Tuesday, February 4, 2014 11:46:55 PM UTC-8, Roger Alsing wrote:
>
> Lets say we have the following senario
>
> * we have an unbounded number of entities
> * each entity may only process one command at a time
> * each entity only process a few messages occasionally and then idle for
> an undefined amount of time
>
> Spawning an actor for each entity would force us to keep atleast one actor
> per entity in memory all the time. which is expensive since the will mostly
> be idle.
>
> What would be the most idiomatic Akka way to deal with this?
>
> Should we instead add an entity Id to each message, and have a custom
> router that directs each message to a pool of actors and create an affinity
> between the entity id and the pooled actor?
> e.g.
>
> someting like:
> var poolIndex = ((IHaveId)message).Id.GetHashCode() % poolSize;
>
> This way, I could direct every message for a specific entity to the same
> underlying worker actor and thus prevent concurrency issues for this entity.
> The worker actor could also fetch the entity on demand and then release it
> once the command completes.
>
> Are there other alternatives?
>
> //Roger
>
--
>>>>>>>>>> Read the docs: http://akka.io/docs/
>>>>>>>>>> Check the FAQ: http://akka.io/faq/
>>>>>>>>>> Search the archives: https://groups.google.com/group/akka-user
---
You received this message because you are subscribed to the Google Groups "Akka
User List" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/akka-user.
For more options, visit https://groups.google.com/groups/opt_out.