Fantom

Login | Register

ActorPool.maxThreads #1279

rosarinjroy
30 Oct 2010

From material I have read so far, the following is the pattern in which a unit of work is given to an Actor: Produce the work. And give the work to a new Actor like:

Actor(ActorPool()).send(work)

A small variation to the pattern above is to have a common ActorPool across all the Actors. That way stopping the actors can be controlled, like:

actorPool := ActorPool()
Actor(actorPool).send(work)

// Later ...
actorPool.stop.join

The above pattern is good if the producer is not interested in the result. This is the pattern that is used in Wisp. The actor sends the response to the client, since it has a response object as a part of the work unit.

One concern I have with the pattern above is that under heavy load, if the server receives 100 concurrent requests, there is a possibility that 100 Actors may be active in 100 threads.

Is there a possibility that I can limit the number of Actors that can be active at any given point of time? At least for a given ActorPool, is there a way I can limit the number of Actors that can be active?

In other words, I am looking for something like this:

maxActiveActors := 10
actorPool := ActorPool(maxActiveActors)

// The following work will be processed immediately, 
// if there is less than maxActiveActors active in the actorPool.
Actor(actorPool).send(work)

What I am looking for is something similar to ExecutorService in Java. Could someone please share if its possible? If its not possible, if you could share the rationale, it would be of great help.

Thank you.

brian
30 Oct 2010

Promoted to ticket #1279 and assigned to brian

My intention has always been to expose the thread pool size, just never got around to it. I will take a look hopefully for this coming build.

rosarinjroy
30 Oct 2010

Brian: Thank you for considering my request. If limited sized ActorPool is yet to be implemented, I would like to request the following points to be considered. These are learnings from ExecutorService in Java.

I understand that creating an Actor is a light weight task. But still consider the other alternative below.

maxActiveActors := 10
actorService := ActorService(maxActiveActors)

// When a new work is created, instead of creating a new Actor,
// hide that complexity from the user and let the user submit the work
// to the service itself.
actorService.send(work).get

// When the pool needs to be shutdown, call shutdown and
// optionally wait for all actors to terminate.
actorService.shutdown.join

The objective is to hide the complexity of creating and maintaining references to Actors from the user. I am not quite sure if ActorService mentioned above could be the same as the ActorPool existing now. That is open for discussion.

The advantage of method above is that it lets the user to have a single queue of work units. And the service can guarantee that the work units will be processed in the same order of submission, though each unit might take different amounts of time.

I also wanted to check out the code and provide a patch. But the "hg clone ..." failed. Could you also point me to any doc you already have to check out and submit a patch?

brian
31 Oct 2010

If I am following your idea correctly you just want to schedule arbitrary units of work across a thread pool. Since creating actors is so cheap, you would just allocate an Actor per unit of work, then the ActorPool would automatically schedule the work across its thread pool. I actually do this a bit in my code, or sometimes if for example I might use one Actor per file or something where I want to ensure serial access to given IO resource.

rosarinjroy
1 Nov 2010

Brian: I don't want to create an Actor per unit of work. I would like to submit the work (using send call) directly to the ActorService. This is a change to current pattern of sending a message to an actor. Please refer to the code snippet I had given in my second post above, that gives a picture of what I am suggesting.

qualidafial
1 Nov 2010

@rosarinjroy: It sounds like you want something like ActorPool.defVal. e.g.

class ActorPool
{
  static const ActorPool defVal := ActorPool()

  ...
}

class Actor
{
  new make(ActorPool pool := ActorPool.defVal, |Obj? -> Obj?|? receive := null)
  {
    ...
  }
}

This way, there would only be one actor pool by default, unless you explicitly created one.

Have I captured the intent of your request correctly?

qualidafial
1 Nov 2010

Also:

BRAAAAAAAAAAAAAIIIIINS!!!

(Happy Halloween)

rosarinjroy
1 Nov 2010

qualidafial: Thanks for the wishes. I would like to have the following facilities:

  • Create an actor pool, which is limited in terms of how many actors can be active at the same time. Not an actor pool that is static and global.
  • There should be a way to submit a work unit without creating new actor instances.

Please see my sample code snippet, which I am copying from my previous post. The proposal I have is modeled after the ExecutorService in Java.

maxActiveActors := 10
actorService := ActorService(maxActiveActors)

// When a new work is created, instead of creating a new Actor,
// hide that complexity from the user and let the user submit the work
// to the service itself.
actorService.send(work).get

// When the pool needs to be shutdown, call shutdown and
// optionally wait for all actors to terminate.
actorService.shutdown.join

brian
1 Nov 2010

Brian: I don't want to create an Actor per unit of work.

Guess I am not understanding this, why not? In your case actor is the unit of work. It is designed this way to be cheap to create and use. You would probably wrap it with some work specific API to your app, but it would be trivial:

// if you want this
service.foo(work).get

// then you might just do something like this
Future foo(Work work)
{
   Actor(pool, |work| { work.doIt }).send(work)
}

rosarinjroy
2 Nov 2010

Brian: Thank you for your clarification. Yes, it is possible to do it. I was thinking if its possible to have it as a part of the standard library itself. Anyway, I think you might want to add support for the limited sized actor pool for now.

brian
8 Nov 2010

Renamed from Is it possible to have a limited sized actor pool to ActorPool.maxThreads

brian
8 Nov 2010

Ticket resolved in 1.0.56

Added a new ActorPool.maxThreads property and updated docLang::Actor chapter

changeset

Login or Register to Reply

Back | All Topics