Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala async/await and parallelization

I'm learning about the uses of async/await in Scala. I have read this in https://github.com/scala/async

Theoretically this code is asynchronous (non-blocking), but it's not parallelized:

def slowCalcFuture: Future[Int] = ...              def combined: Future[Int] = async {                   await(slowCalcFuture) + await(slowCalcFuture) } val x: Int = Await.result(combined, 10.seconds)     

whereas this other one is parallelized:

def combined: Future[Int] = async {   val future1 = slowCalcFuture   val future2 = slowCalcFuture   await(future1) + await(future2) } 

The only difference between them is the use of intermediate variables. How can this affect the parallelization?

like image 589
Sanete Avatar asked Nov 20 '13 09:11

Sanete


People also ask

What is async and await in Scala?

This is a proposal to add constructs that simplify asynchronous and concurrent programming in Scala. The main constructs, async and await, are inspired by similar constructs introduced in C# 5.0.

What is Scala-async?

Scala-async is a library for asynchronous programming. It provides a simple API to handle asynchronous method calls using the imperative way, which in some cases is more convenient. It was first added in C# and F# and then ported to other languages like Scala, Python, Javascript etc.

How does async work on Line 1?

Line 1 defines an asynchronous method: it returns a Future. Line 2 begins an async block. During compilation, the contents of this block will be analyzed to identify the await calls, and transformed into non-blocking code. Control flow will immediately pass to line 5, as the computation in the async block is not executed on the caller's thread.

What is async object in Java?

Async is an object with only two methods namely ‘async ()’ and ‘await ()’. The main use case of Async object is to conveniently and efficiently code in asynchronous way. It can be considered as another alternative of low-level callbacks or high order functions like map and flat-map.


2 Answers

Since it's similar to async & await in C#, maybe I can provide some insight. In C#, it's a general rule that Task that can be awaited should be returned 'hot', i.e. already running. I assume it's the same in Scala, where the Future returned from the function does not have to be explicitly started, but is just 'running' after being called. If it's not the case, then the following is pure (and probably not true) speculation.

Let's analyze the first case:

async {     await(slowCalcFuture) + await(slowCalcFuture) } 

We get to that block and hit the first await:

async {     await(slowCalcFuture) + await(slowCalcFuture)     ^^^^^ } 

Ok, so we're asynchronously waiting for that calculation to finish. When it's finished, we 'move on' with analyzing the block:

async {     await(slowCalcFuture) + await(slowCalcFuture)                             ^^^^^ } 

Second await, so we're asynchronously waiting for second calculation to finish. After that's done, we can calculate the final result by adding two integers.

As you can see, we're moving step-by-step through awaits, awaiting Futures as they come one by one.

Let's take a look at the second example:

async {   val future1 = slowCalcFuture   val future2 = slowCalcFuture   await(future1) + await(future2) } 

OK, so here's what (probably) happens:

async {   val future1 = slowCalcFuture // >> first future is started, but not awaited   val future2 = slowCalcFuture // >> second future is started, but not awaited   await(future1) + await(future2)   ^^^^^ } 

Then we're awaiting the first Future, but both of the futures are currently running. When the first one returns, the second might have already completed (so we will have the result available at once) or we might have to wait for a little bit longer.

Now it's clear that second example runs two calculations in parallel, then waits for both of them to finish. When both are ready, it returns. First example runs the calculations in a non-blocking way, but sequentially.

like image 161
Patryk Ćwiek Avatar answered Sep 28 '22 05:09

Patryk Ćwiek


the answer by Patryk is correct if a little difficult to follow. the main thing to understand about async/await is that it's just another way of doing Future's flatMap. there's no concurrency magic behind the scenes. all the calls inside an async block are sequential, including await which doesn't actually block the executing thread but rather wraps the rest of the async block in a closure and passes it as a callback on completion of the Future we're waiting on. so in the first piece of code the second calculation doesn't start until the first await has completed since no one started it prior to that.

like image 35
Mikha Avatar answered Sep 28 '22 05:09

Mikha