Рассмотрим следующее:
import scala.concurrent._
import scala.concurrent.duration.Duration.Inf
import scala.concurrent.ExecutionContext.Implicits.global
def slowInt(i: Int) = { Thread.sleep(200); i }
def slowAdd(x: Int, y: Int) = { Thread.sleep(100); x + y }
def futures = (1 to 20).map(i => future(slowInt(i)))
def timeFuture(fn: => Future[_]) = {
val t0 = System.currentTimeMillis
Await.result(fn, Inf)
println((System.currentTimeMillis - t0) / 1000.0 + "s")
}
обе следующие печати ~ 2.5s:
// Use Future.reduce directly (Future.traverse is no different)
timeFuture { Future.reduce(futures)(slowAdd) }
// First wait for all results to come in, convert to Future[List], and then map the List[Int]
timeFuture { Future.sequence(futures).map(_.reduce(slowAdd)) }
Насколько я понимаю, причиной этого является то, что Future.reduce/traverse
является общим и, следовательно, не работает быстрее с ассоциативным оператором, однако есть ли простой способ определить вычисление, в котором начнется свертывание/восстановление как только будет доступно хотя бы 2 значения (или 1 в случае fold
), так что, пока некоторые элементы в списке все еще сгенерированы, уже сгенерированные уже вычисляются на?