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.

Reply via email to