title: Akka - worse performance with more actors
body: <p>I'm trying out some parallel programming with Scala and Akka, which I'm new to. I've got a pretty simple Monte Carlo Pi application (approximates pi in a circle) which I've built in several languages. However the performance of the version I've built in Akka is puzzling me. </p>
  
  <p>I have a sequential version written in pure Scala that tends to take roughly 400ms to complete. </p>
  
  <p>In comparison with 1 worker actor the Akka version takes around 300-350ms, however as I increase the number of actors that time increases dramatically. With 4 actors the time can be anywhere between 500ms all the way up to 1200ms or higher. </p>
  
  <p>The number of iterations are being divided up between the worker actors, so ideally performance should be getting better the more of them there are, currently it's getting significantly worse.</p>
  
  <p>My code is</p>
  
  <pre><code>object MCpi{
    //Declare initial values
    val numWorkers = 2
    val numIterations = 10000000
  
    //Declare messages that will be sent to actors
    sealed trait PiMessage
    case object Calculate extends PiMessage
    case class Work(iterations: Int) extends PiMessage
    case class Result(value: Int) extends PiMessage
    case class PiApprox(pi: Double, duration: Double)
  
    //Main method
    def main(args: Array[String]): Unit = {
      val system = ActorSystem("MCpi_System") //Create Akka system
      val master = system.actorOf(Props(new MCpi_Master(numWorkers, numIterations))) //Create Master Actor
      println("Starting Master")
  
      master ! Calculate //Run calculation
    }
  }
  
  //Master
  class MCpi_Master(numWorkers: Int, numIterations: Int) extends Actor{
  
    var pi: Double = _ // Store pi
    var quadSum: Int = _ //the total number of points inside the quadrant
    var numResults: Int = _ //number of results returned
    val startTime: Double = System.currentTimeMillis() //calculation start time
  
    //Create a group of worker actors
    val workerRouter = context.actorOf(
      Props[MCpi_Worker].withRouter(RoundRobinPool(numWorkers)), name = "workerRouter")
    val listener = context.actorOf(Props[MCpi_Listener], name = "listener")
  
    def receive = {
      //Tell workers to start the calculation
        //For each worker a message is sent with the number of iterations it is to perform,
        //iterations are split up between the number of workers.
      case Calculate =&gt; for(i &lt;- 0 until numWorkers) workerRouter ! Work(numIterations / numWorkers);
  
        //Receive the results from the workers
          case Result(value) =&gt;
              //Add up the total number of points in the circle from each worker
        quadSum += value
              //Total up the number of results which have been received, this should be 1 for each worker
        numResults += 1
  
        if(numResults == numWorkers) { //Once all results have been collected
            //Calculate pi
            pi = (4.0 * quadSum) / numIterations
            //Send the results to the listener to output
          listener ! PiApprox(pi, duration = System.currentTimeMillis - startTime)
          context.stop(self)
        }
    }
  }
  //Worker
  class MCpi_Worker extends Actor {
    //Performs the calculation
    def calculatePi(iterations: Int): Int = {
  
      val r = scala.util.Random // Create random number generator
      var inQuadrant: Int = 0 //Store number of points within circle
  
      for(i &lt;- 0 to iterations){
        //Generate random point
        val X = r.nextFloat()
        val Y = r.nextFloat()
  
        //Determine whether or not the point is within the circle
        if(((X * X) + (Y * Y)) &lt; 1.0)
          inQuadrant += 1
      }
      inQuadrant //return the number of points within the circle
    }
  
    def receive = {
      //Starts the calculation then returns the result
      case Work(iterations) =&gt; sender ! Result(calculatePi(iterations))
    }
  }
  
  //Listener
  class MCpi_Listener extends Actor{ //Recieves and prints the final result
    def receive = {
      case PiApprox(pi, duration) =&gt;
          //Print the results
        println("\n\tPi approximation: \t\t%s\n\tCalculation time: \t%s".format(pi, duration))
          //Print to a CSV file
          val pw: FileWriter = new FileWriter("../../../..//Results/Scala_Results.csv", true)
          pw.append(duration.toString())
          pw.append("\n")
          pw.close()
        context.system.terminate()
  
    }
  }
  </code></pre>
  
  <p>The plain Scala sequential version is</p>
  
  <pre><code>object MCpi {
      def main(args: Array[String]): Unit = {
          //Define the number of iterations to perform
          val iterations = args(0).toInt;
          val resultsPath = args(1);
  
          //Get the current time
          val start = System.currentTimeMillis()
  
  
          // Create random number generator
          val r = scala.util.Random
          //Store number of points within circle
          var inQuadrant: Int = 0
  
          for(i &lt;- 0 to iterations){
              //Generate random point
              val X = r.nextFloat()
              val Y = r.nextFloat()
  
              //Determine whether or not the point is within the circle
              if(((X * X) + (Y * Y)) &lt; 1.0)
                  inQuadrant += 1
          }
          //Calculate pi
          val pi = (4.0 * inQuadrant) / iterations
          //Get the total time
          val time = System.currentTimeMillis() - start
          //Output values
          println("Number of Iterations: " + iterations)
          println("Pi has been calculated as: " + pi)
          println("Total time taken: " + time + " (Milliseconds)")
  
          //Print to a CSV file
          val pw: FileWriter = new FileWriter(resultsPath + "/Scala_Results.csv", true)
          pw.append(time.toString())
          pw.append("\n")
          pw.close()
      }
  }
  </code></pre>
  
  <p>Any suggestions as to why this is happening or how I can improve performance would be very welcome. </p>
  
  <p>Edit: I'd like to thank all of you for your answers, this is my first question on this site and all the answers are extremely helpful, I have plenty to look in to now :)</p>