Akka actors versus Scala actors : control the message throughput of actors
In the post following this one, I show how to enhance the example code in order to be able to process a very high number of messages : Akka actors : 10 millions messages processed (1s / message) in 75 seconds !
Scala default actor system doesn't come with any mechanism to control messages throughput between actors, so it is up to you to implement such feature in order to avoid OutOfMemory problem, in particular when actors are not processing messages at the same rate.
Akka framework is very interesting because it brings you all the features to control and manage throughputs. Let's see how it work through a simple example :
The good news is that akka support bounded actor mailboxes, just add a configuration file with such content :
Of course it will take a long time to process as each message requires 1s (and actors are blocked during 1s because of Thread.sleep call, which monopolize a thread during the same duration => waste of resources)... If we want to reduce the processing time although each message requires 1s to be taken into account, we'll have to load-balance message processing accross a high number of actors.
CONTEXT : Scala 2.9.1 / SBT 0.11.2 / AKKA 2.0-rc2 / sbteclipse 2.0.0
Scala default actor system doesn't come with any mechanism to control messages throughput between actors, so it is up to you to implement such feature in order to avoid OutOfMemory problem, in particular when actors are not processing messages at the same rate.
Akka framework is very interesting because it brings you all the features to control and manage throughputs. Let's see how it work through a simple example :
Each message sent is more than 50 bytes, so a JVM with a 512Mo of maximum heap size will quickly run out of memory.
import akka.actor._
sealed trait MyMessage
case class DoItMessage(cmd:String) extends MyMessage
object Dummy {
def main(args:Array[String]) {
val system=ActorSystem("DummySystem")
val processor = system.actorOf(Props[MyMessageProcessor],name="default")
for(i <- 1 to 10000000) {
processor ! DoItMessage("Do the job with ID#%d now".format(i))
}
println("All jobs sent")
}
}
class MyMessageProcessor extends Actor {
def receive = {
case _:DoItMessage => Thread.sleep(1000)
}
}
The good news is that akka support bounded actor mailboxes, just add a configuration file with such content :
And make this configuration file taken into account with the following code update :
dummy {
akka {
loglevel = WARNING
actor {
default-dispatcher {
mailbox-capacity = 10000
}
}
}
}
This time if you run again the previous code, you'll get a stable memory footprint :
import com.typesafe.config.ConfigFactory
val system=ActorSystem("DummySystem",ConfigFactory.load.getConfig("dummy"))
Of course it will take a long time to process as each message requires 1s (and actors are blocked during 1s because of Thread.sleep call, which monopolize a thread during the same duration => waste of resources)... If we want to reduce the processing time although each message requires 1s to be taken into account, we'll have to load-balance message processing accross a high number of actors.
CONTEXT : Scala 2.9.1 / SBT 0.11.2 / AKKA 2.0-rc2 / sbteclipse 2.0.0