Note that there are some explanatory texts on larger screens.

plurals
  1. POScala stateful actor, recursive calling faster than using vars?
    text
    copied!<p>Sample code below. I'm a little curious why MyActor is faster than MyActor2. MyActor recursively calls process/react and keeps state in the function parameters whereas MyActor2 keeps state in vars. MyActor even has the extra overhead of tupling the state but still runs faster. I'm wondering if there is a good explanation for this or if maybe I'm doing something "wrong".</p> <p>I realize the performance difference is not significant but the fact that it is there and consistent makes me curious what's going on here.</p> <p>Ignoring the first two runs as warmup, I get:</p> <p>MyActor: 559 511 544 529</p> <p>vs.</p> <p>MyActor2: 647 613 654 610</p> <pre><code>import scala.actors._ object Const { val NUM = 100000 val NM1 = NUM - 1 } trait Send[MessageType] { def send(msg: MessageType) } // Test 1 using recursive calls to maintain state abstract class StatefulTypedActor[MessageType, StateType](val initialState: StateType) extends Actor with Send[MessageType] { def process(state: StateType, message: MessageType): StateType def act = proc(initialState) def send(message: MessageType) = { this ! message } private def proc(state: StateType) { react { case msg: MessageType =&gt; proc(process(state, msg)) } } } object MyActor extends StatefulTypedActor[Int, (Int, Long)]((0, 0)) { override def process(state: (Int, Long), input: Int) = input match { case 0 =&gt; (1, System.currentTimeMillis()) case input: Int =&gt; state match { case (Const.NM1, start) =&gt; println((System.currentTimeMillis() - start)) (Const.NUM, start) case (s, start) =&gt; (s + 1, start) } } } // Test 2 using vars to maintain state object MyActor2 extends Actor with Send[Int] { private var state = 0 private var strt = 0: Long def send(message: Int) = { this ! message } def act = loop { react { case 0 =&gt; state = 1 strt = System.currentTimeMillis() case input: Int =&gt; state match { case Const.NM1 =&gt; println((System.currentTimeMillis() - strt)) state += 1 case s =&gt; state += 1 } } } } // main: Run testing object TestActors { def main(args: Array[String]): Unit = { val a = MyActor // val a = MyActor2 a.start() testIt(a) } def testIt(a: Send[Int]) { for (_ &lt;- 0 to 5) { for (i &lt;- 0 to Const.NUM) { a send i } } } } </code></pre> <p>EDIT: Based on Vasil's response, I removed the loop and tried it again. And then MyActor2 based on vars leapfrogged and now might be around 10% or so faster. So... lesson is: if you are confident that you won't end up with a stack overflowing backlog of messages, and you care to squeeze every little performance out... don't use loop and just call the act() method recursively.</p> <p>Change for MyActor2:</p> <pre><code> override def act() = react { case 0 =&gt; state = 1 strt = System.currentTimeMillis() act() case input: Int =&gt; state match { case Const.NM1 =&gt; println((System.currentTimeMillis() - strt)) state += 1 case s =&gt; state += 1 } act() } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload