I modified the original to be correct, theoretically when your AtomicLong 
reaches the *Long.MAX_VALUE* + 1 it will shift to *Long.MIN_VALUE* making 
the mod (%) function return negative which will make the application fail 
due to invalid list index *-list.get(neg_index)-*

In practice that is unlikely to happen but there might be some crazy lab 
running DNA sequencing so in practice infinite is now reachable, could take 
hours, days or weeks, but once it happen, original *RoundRobinRountingLogic* 
will fail, perf tests concluded that at least in Java 8 atomic adder + mod 
is faster than CAS, but the class needs to be modified from this:

final class RoundRobinRoutingLogic extends RoutingLogic {
  val next = new AtomicLong(0)


  override def select(message: Any, routees: immutable.IndexedSeq[Routee]): 
Routee =
    if (routees.isEmpty) NoRoutee
    else routees((next.getAndIncrement % routees.size).asInstanceOf[Int])

}

To this, not sure if it is going to compile, I'm not a Scala programmer, 
not sure if the "asInstanceOf" is needed anymore, Integer or Long they will 
eventually overflow and go to their MIN_VALUE so why bother with a Long?

It looks to me Long was put there with fear of reaching MAX_VALUE causing a 
failure, well, it won't fail because overflows will just shift a bit, but 
it will fail because mod(%) will return negative *-list.get(neg_index)-*, 
so here is the original with Math.abs and AtomicInteger instead:

final class RoundRobinRoutingLogic extends RoutingLogic {
  val next = new AtomicInteger(0)


  override def select(message: Any, routees: immutable.IndexedSeq[Routee]): 
Routee =
    if (routees.isEmpty) NoRoutee
    else routees(Math.abs(next.getAndIncrement % routees.size).asInstanceOf[
Int])

}


*JMH perf tested results:*

Benchmark            Mode  Cnt          Score          Error  Units
CASvsMOD.intCAS_1   thrpt    5   76444721.566 ±   813686.931  ops/s
CASvsMOD.intCAS_4   thrpt    5   73853879.600 ±   689854.722  ops/s
CASvsMOD.intCAS_8   thrpt    5   76352315.163 ±  2300065.091  ops/s
CASvsMOD.intMOD_1   thrpt    5  131541916.778 ±  3400828.887  ops/s
CASvsMOD.intMOD_4   thrpt    5   96787272.406 ±  1540417.674  ops/s
CASvsMOD.intMOD_8   thrpt    5   96954428.161 ±  1007965.370  ops/s
CASvsMOD.longMOD_1  thrpt    5  129730846.046 ± 23522696.956  ops/s
CASvsMOD.longMOD_4  thrpt    5   96930440.731 ±  1549403.070  ops/s
CASvsMOD.longMOD_8  thrpt    5   96882920.242 ±  1342011.843  ops/s


JMH perf source code:

import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;


import java.io.IOException;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;


@State(Scope.Benchmark)
public class CASvsMOD {


  private final AtomicInteger nextInt = new AtomicInteger();
  private final AtomicLong nextLong = new AtomicLong();


  private int nextInt(int routees) {
    return nextInt.accumulateAndGet(1, (index, increment) -> ++index < 
routees ? index : 0);
  }


  @Benchmark
  public void intCAS_1() {
    nextInt(1);
  }


  @Benchmark
  public void intCAS_4() {
    nextInt(4);
  }


  @Benchmark
  public void intCAS_8() {
    nextInt(8);
  }


  private int nextIntWithMod(int routees) {
    return Math.abs(nextInt.incrementAndGet() % routees);
  }


  @Benchmark
  public void intMOD_1() {
    nextIntWithMod(1);
  }


  @Benchmark
  public void intMOD_4() {
    nextIntWithMod(4);
  }


  @Benchmark
  public void intMOD_8() {
    nextIntWithMod(8);
  }


  private long nextLong(int routees) {
    return Math.abs(nextLong.incrementAndGet() % routees);
  }


  @Benchmark
  public void longMOD_1() {
    nextLong(1);
  }


  @Benchmark
  public void longMOD_4() {
    nextLong(4);
  }


  @Benchmark
  public void longMOD_8() {
    nextLong(8);
  }


  public static void main(String[] args) throws RunnerException, IOException 
{
    final Options opt = new OptionsBuilder().
      include(CASvsMOD.class.getSimpleName()).
      warmupIterations(5).
      measurementIterations(5).
      forks(1).
      build();
    new Runner(opt).run();
  }
}


Why am I proposing code here?, well, I tried to import and compile Akka on 
IntelliJ *-I have latest IntelliJ with Scala plugin-*, but I gave up 
because several issues I didn't have the time nor patience to resolve like 
SBT, so this is the best I can do.

-- 
>>>>>>>>>>      Read the docs: http://akka.io/docs/
>>>>>>>>>>      Check the FAQ: 
>>>>>>>>>> http://doc.akka.io/docs/akka/current/additional/faq.html
>>>>>>>>>>      Search the archives: https://groups.google.com/group/akka-user
--- 
You received this message because you are subscribed to the Google Groups "Akka 
User List" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to akka-user+unsubscr...@googlegroups.com.
To post to this group, send email to akka-user@googlegroups.com.
Visit this group at http://groups.google.com/group/akka-user.
For more options, visit https://groups.google.com/d/optout.

Reply via email to