Removing uuid tracking in MessageDispatcher, isn't needed and will be reducing the overall memory footprint per actor

This commit is contained in:
Viktor Klang 2011-10-18 15:09:35 +02:00
parent 65868d7c96
commit 304d39d839
3 changed files with 22 additions and 25 deletions

View file

@ -120,17 +120,11 @@ object ActorModelSpec {
protected[akka] abstract override def register(actor: ActorCell) { protected[akka] abstract override def register(actor: ActorCell) {
getStats(actor.ref).registers.incrementAndGet() getStats(actor.ref).registers.incrementAndGet()
super.register(actor) super.register(actor)
//printMembers("after registering " + actor)
} }
protected[akka] abstract override def unregister(actor: ActorCell) { protected[akka] abstract override def unregister(actor: ActorCell) {
getStats(actor.ref).unregisters.incrementAndGet() getStats(actor.ref).unregisters.incrementAndGet()
super.unregister(actor) super.unregister(actor)
//printMembers("after unregistering " + actor)
}
def printMembers(when: String) {
System.err.println(when + " then " + uuids.toArray.toList.map(_.toString.split("-")(0)).mkString("==> ", ", ", "<=="))
} }
protected[akka] abstract override def dispatch(invocation: Envelope) { protected[akka] abstract override def dispatch(invocation: Envelope) {

View file

@ -81,7 +81,7 @@ class DispatcherActorSpec extends AkkaSpec {
(1 to 100) foreach { _ slowOne ! "ping" } (1 to 100) foreach { _ slowOne ! "ping" }
fastOne ! "sabotage" fastOne ! "sabotage"
start.countDown() start.countDown()
val result = latch.await(5, TimeUnit.SECONDS) val result = latch.await(10, TimeUnit.SECONDS)
fastOne.stop() fastOne.stop()
slowOne.stop() slowOne.stop()
assert(result === true) assert(result === true)

View file

@ -70,8 +70,8 @@ object MessageDispatcher {
abstract class MessageDispatcher(val app: AkkaApplication) extends Serializable { abstract class MessageDispatcher(val app: AkkaApplication) extends Serializable {
import MessageDispatcher._ import MessageDispatcher._
protected val uuids = new ConcurrentSkipListSet[Uuid]
protected val _tasks = new AtomicLong(0L) protected val _tasks = new AtomicLong(0L)
protected val _actors = new AtomicLong(0L)
protected val guard = new ReentrantGuard protected val guard = new ReentrantGuard
protected val active = new Switch(false) protected val active = new Switch(false)
@ -123,7 +123,7 @@ abstract class MessageDispatcher(val app: AkkaApplication) extends Serializable
final def detach(actor: ActorCell) { final def detach(actor: ActorCell) {
guard withGuard { guard withGuard {
unregister(actor) unregister(actor)
if (uuids.isEmpty && _tasks.get == 0) { if (_tasks.get == 0 && _actors.get == 0) {
shutdownSchedule match { shutdownSchedule match {
case UNSCHEDULED case UNSCHEDULED
shutdownSchedule = SCHEDULED shutdownSchedule = SCHEDULED
@ -155,7 +155,7 @@ abstract class MessageDispatcher(val app: AkkaApplication) extends Serializable
private val taskCleanup: () Unit = private val taskCleanup: () Unit =
() if (_tasks.decrementAndGet() == 0) { () if (_tasks.decrementAndGet() == 0) {
guard withGuard { guard withGuard {
if (_tasks.get == 0 && uuids.isEmpty) { if (_tasks.get == 0 && _actors.get == 0) {
shutdownSchedule match { shutdownSchedule match {
case UNSCHEDULED case UNSCHEDULED
shutdownSchedule = SCHEDULED shutdownSchedule = SCHEDULED
@ -173,9 +173,8 @@ abstract class MessageDispatcher(val app: AkkaApplication) extends Serializable
* and only call it under the dispatcher-guard, see "attach" for the only invocation * and only call it under the dispatcher-guard, see "attach" for the only invocation
*/ */
protected[akka] def register(actor: ActorCell) { protected[akka] def register(actor: ActorCell) {
if (uuids add actor.uuid) { _actors.incrementAndGet()
systemDispatch(SystemEnvelope(actor, Create, NullChannel)) //FIXME should this be here or moved into ActorCell.start perhaps? systemDispatch(SystemEnvelope(actor, Create, NullChannel)) //FIXME should this be here or moved into ActorCell.start perhaps?
} else System.err.println("Couldn't register: " + actor)
} }
/** /**
@ -183,12 +182,11 @@ abstract class MessageDispatcher(val app: AkkaApplication) extends Serializable
* and only call it under the dispatcher-guard, see "detach" for the only invocation * and only call it under the dispatcher-guard, see "detach" for the only invocation
*/ */
protected[akka] def unregister(actor: ActorCell) { protected[akka] def unregister(actor: ActorCell) {
if (uuids remove actor.uuid) { _actors.decrementAndGet()
val mailBox = actor.mailbox val mailBox = actor.mailbox
mailBox.becomeClosed() mailBox.becomeClosed()
actor.mailbox = deadLetterMailbox //FIXME getAndSet would be preferrable here actor.mailbox = deadLetterMailbox //FIXME getAndSet would be preferrable here
cleanUpMailboxFor(actor, mailBox) cleanUpMailboxFor(actor, mailBox)
} else System.err.println("Couldn't unregister: " + actor)
} }
/** /**
@ -222,7 +220,7 @@ abstract class MessageDispatcher(val app: AkkaApplication) extends Serializable
shutdownSchedule = SCHEDULED shutdownSchedule = SCHEDULED
app.scheduler.scheduleOnce(this, timeoutMs, TimeUnit.MILLISECONDS) app.scheduler.scheduleOnce(this, timeoutMs, TimeUnit.MILLISECONDS)
case SCHEDULED case SCHEDULED
if (uuids.isEmpty && _tasks.get == 0) { if (_tasks.get == 0) {
active switchOff { active switchOff {
shutdown() // shut down in the dispatcher's references is zero shutdown() // shut down in the dispatcher's references is zero
} }
@ -243,16 +241,21 @@ abstract class MessageDispatcher(val app: AkkaApplication) extends Serializable
/** /**
* After the call to this method, the dispatcher mustn't begin any new message processing for the specified reference * After the call to this method, the dispatcher mustn't begin any new message processing for the specified reference
*/ */
def suspend(actor: ActorCell): Unit = def suspend(actor: ActorCell): Unit = {
if (uuids.contains(actor.uuid)) actor.mailbox.becomeSuspended() val mbox = actor.mailbox
if (mbox.dispatcher eq this)
mbox.becomeSuspended()
}
/* /*
* After the call to this method, the dispatcher must begin any new message processing for the specified reference * After the call to this method, the dispatcher must begin any new message processing for the specified reference
*/ */
def resume(actor: ActorCell): Unit = if (uuids.contains(actor.uuid)) { def resume(actor: ActorCell): Unit = {
val mbox = actor.mailbox val mbox = actor.mailbox
mbox.becomeOpen() if (mbox.dispatcher eq this) {
registerForExecution(mbox, false, false) mbox.becomeOpen()
registerForExecution(mbox, false, false)
}
} }
/** /**