This is an example of hot-swapping actor behavior in Akka using the become method. This demo was not part of my "Akka: Scaling Up and Out with Actors"(http://java.ociweb.com/javasig/knowledgebase/2011-06/index.html) talk given at the St. Louis JavaSIG on June 9th, 2011. It was left out due to time constraints on the presentation.
Inspired by a post on Dale Schumaker's "The Computational Actor's Guild" site (http://dalnefre.net/drupal/node/23), this demonstrates an actor that builds a ring of of actors of a specified size that then passes a message around the ring a given number of times. What's interesting about this implementation is that the actor uses become to change the behavior of a Actor from one that helps construct the ring to one that handles the message by passing to the next actor in the ring.
object RingBecomeDemo {
class NodeActor(id:Int, start:Long) extends Actor {
def receive = {
case n:Int => self ! (self, n)
case (top:ActorRef, n:Int) => {
if (id == 0) {
become {
case np:Int => if (np == 0) {
self.stop
printf("Time %d ms\r\n", System.currentTimeMillis - start)
} else {
printf("decrementing from %d\r\n", np)
top ! (np - 1)
}
}
top ! n
} else {
val next = Actor.actorOf(new NodeActor(id-1, start)).start
next ! (top, n)
become {
case np:Int => {
next ! np
if (np == 0) {
self.stop
}
}
}
}
}
}
}
def main(args:Array[String]) {
val ring = Actor.actorOf(new NodeActor(1000000, System.currentTimeMillis)).start
ring ! 10
}
}
This implementation creates a million nodes and times how long it takes to construct the ring and pass an integer around 10 times.
Here (http://sites.google.com/site/compulsiontocode/blog/ring-become.zip) is a file containing code above. Gradle is required to run it. To execute, unzip and enter 'gradle RingBecomeDemo' within the 'ring-become' directory.
One million node requires a significant heap size. To reduce the number nodes, change the first parameter passed to the NodeActor constructor. The heap size can be changed by editing the RingBecomeDemo task in the build.gradle file:
task RingBecomeDemo(type:JavaExec, dependsOn: classes) {
jvmArgs = System.getProperty("sun.arch.data.model").equals("64") ? ["-Xms2048m", "-Xmx2048m"] : ["-Xms1024m", "-Xmx1024m", "-server"]
classpath = sourceSets.main.runtimeClasspath
main = "tfd.ringbecome.RingBecomeDemo"
}
A follow-up post is planned compare this implementation to one in Erlang including performance.
