2017-09-30 15 views
-1

私はAkka cookbookを読んでおり、1つのサンプルで機能の性能を向上させることが興味深いことがわかりました。俳優クラスのなぜ非同期計算でプログラムが遅くなるのですか?

object HelloAkkaActorSystem extends App { 
    implicit val timeout = Timeout(50 seconds) 
    val actorSystem = ActorSystem("HelloAkka") 
    val actor = actorSystem.actorOf(Props[FibonacciActor]) 
    // asking for result from actor 
    val future = (actor ? 6).mapTo[Int] 
    val st = System.nanoTime() 
    val fiboacciNumber = Await.result(future, 60 seconds) 
    println("Elapsed time: " + (System.nanoTime() - st)/math.pow(10, 6)) 
    println(fiboacciNumber) 
} 

そして、2つの実装: 私は、次のクライアントオブジェクトを持っています。

まず:0.12ミリ、360ミリ秒でSecondで行わ私のマシンFirstバリアントで

class FibonacciActor extends Actor { 
    override def receive: PartialFunction[Any, Unit] = { 
    case num : Int => 
     val fibonacciNumber = fib(num) 
     val s = sender() 
     fibonacciNumber.onComplete { 
     case Success(x) => s ! x 
     case Failure(e) => s ! -1 
     } 
    } 
    def fib(n : Int) : Future[Int] = n match { 
    case 0 | 1 => Future{ n } 
    case _ => 
     fib(n-1).flatMap(n_1 => 
     fib(n-2).map(n_2 => 
      n_1 + n_2)) 
    } 
} 

class FibonacciActor extends Actor { 
    override def receive: Receive = { 
    case num : Int => 
     val fibonacciNumber = fib(num) 
     sender ! fibonacciNumber 
    } 
    def fib(n : Int) : Int = n match { 
    case 0 | 1 => n 
    case _ => fib(n-1) + fib(n-2) 
    } 
} 

セカンド。したがって、Secondは300倍遅くなります。 htopを使用すると、Firstバリアントは2番目のすべての4に対して1コアを使用することがわかりました。 あまりにも多くの非同期タスクが生成されるためですか?どのようにfib(n: Int)方法をスピードアップするには?

答えて

1

まず、ベンチマーク結果は現実には反映されない可能性があります。 JVMは実際にはその例でそれを実行しているあなたのコードをJITingするより多くの時間を費やしているでしょう。 JVMがするので

一般

How do I write a correct micro-benchmark in Java?

、Javaで、あなたは(単にコンパイルが起こっているすべてのJITを確実にするためにウォームアップとして、10000回程度物事を行う必要があります。ここではSOマイクロベンチマークを作成する上で掲示良いことですコードを実行しながら分析し、メソッドがたくさん呼び出されると、それは世界を止め、それを実行する代わりにマシンコードにコンパイルします。上記のベンチマークでは、マシンコードにコンパイルされると、ほとんど解釈されます。つまり、実行速度が遅くなり、ホットスポットとして検出される可能性がありますので、コンパイルしてからコンパイルし直してください。なぜあなたはループの中でそれを数千回実行しなければならないのですか?あなたが実際に何かを開始する前に、すべてが完了していることを確認してください。

第2に、あなたの質問に答えるために、の実行ごとにのfib(全体の操作ではなく、fibの実行の各繰り返し)を送信しています。これはわずか数ナノ秒実行するには、スレッドプールに移動します。スレッドプールに何かをディスパッチするオーバーヘッドは数マイクロ秒です。スレッドプールを送信するのは数ナノ秒しかかかりませんので、操作のコストを1000倍にして "非同期"計算コストの高い操作をスレッドプールにディスパッチする必要があります。たとえば、実行には数秒かかる操作です。非常に小さな操作をスレッドプールにディスパッチするのは意味がありません。

+0

答えをいただきありがとうございます。ベンチマークとJVMウォームアップの正しさについては皆さんが書いています。しかし、ベンチマークの結果が正しくない場合でも、どちらの場合も正しくありません。だから、第二の変種が300倍遅くなるという私の仮定は正しい。それは単に競争のためです。私の2番目の質問については、非同期計算で 'fib'メソッドを高速化する方法はありますか? –

関連する問題