2017-12-24 21 views
1

私はこのような機能を持っていると仮定します。Scala Futureのマップはオーバーヘッドを追加しますか?

import scala.concurrent._ 

def plus2Future(fut: Future[Int]) 
       (implicit ec: ExecutionContext): Future[Int] = fut.map(_ + 2) 

は今、私は新しいFutureを作成するplus2Futureを使用しています:

import import scala.concurrent.ExecutionContext.Implicits.global 
val fut1 = Future { 0 } 
val fut2 = plus2Future(fut1) 

は今、同じスレッド上としての機能plus2常に実行していfut1?私はそれがないと思う。
は新しいRunnableなどを作成し、スレッドコンテキストスイッチのオーバーヘッドを追加plus2Futuremapを使用していますか?

+1

*あなたは、これはあなたのコードのベンチマークからのオーバーヘッドで決定した*スレッドコンテキストの切り替えに伴うオーバーヘッドを回避するには? –

+1

同じスレッドで実行したい場合は、 'Future {plus2(plus1(x))}'を実行してください。あるいは単に 'PLUS2(PLUS1(X))' ...だけでなく、将来を作成するための「オーバーヘッド」を避けるために:) – Dima

+0

@YuvalItzchakovありませんが、私は、ベンチマークのコードをしませんでした。私はその質問を言い換えるつもりです。 – Michael

答えて

2

マップをplus2で使用していますか?スレッドコンテキストのオーバーヘッドを追加しますか? 新しいランナブルなどを作成しますか? FutureDefaultPromise経由)のデフォルトの実装上の

map

は、次のとおりです。 onCompleteは新しい CallableRunnableを作成し、最終的に呼び出します

def map[S](f: T => S)(implicit executor: ExecutionContext): Future[S] = { // transform(f, identity) 
    val p = Promise[S]() 
    onComplete { v => p complete (v map f) } 
    p.future 
} 

dispatchOrAddCallback:への呼び出しをディスパッチ

/** Tries to add the callback, if already completed, it dispatches the callback to be executed. 
* Used by `onComplete()` to add callbacks to a promise and by `link()` to transfer callbacks 
* to the root promise when linking two promises togehter. 
*/ 
@tailrec 
private def dispatchOrAddCallback(runnable: CallbackRunnable[T]): Unit = { 
    getState match { 
    case r: Try[_]   => runnable.executeWithValue(r.asInstanceOf[Try[T]]) 
    case _: DefaultPromise[_] => compressedRoot().dispatchOrAddCallback(runnable) 
    case listeners: List[_] => if (updateState(listeners, runnable :: listeners))() else dispatchOrAddCallback(runnable) 
    } 
} 

基礎となる実行コンテキストこれは、将来の実行方法と場所を決定することが実装ExecutionContextまでであることを意味するので、「それはここやそこに走る」という決定論的な答えを与えることはできません。 Promiseとコールバックオブジェクトの両方の割り当てがあることがわかります。一般的に

私は、コードをベンチマークし、これがボトルネックであることが判明していない限り、私は、このことを心配しません。時間の無制限の量が2行のコードの間に経過することができるので

+0

答えをありがとう。今、デフォルトの 'ExecutionContext'のためにどのように動作するかを調べるのは面白いです。 – Michael

+0

ボトルネックはほとんどありません。ちょうどそれがどのように動作するのか理解したい。このよう – Michael

+0

@Michael:https://github.com/scala/scala/blob/2.12.x/​​src/library/scala/concurrent/impl/ExecutionContextImpl.scala#L20(Scalaの2.12.x) –

1

いいえ、それが(決定的)(ECのみつのスレッドを持っていない限り)同じ糸を使用することはできません。

関連する問題