scala/scala-async

Using async/await as a general solution for handling with async code

rterekhov opened this issue · 2 comments

We look with interest on using async/await as a general approach for working with futures in our project.
We did some tests on the library but found out that it produce much more java byte code then map/flatMap does in the same in the same situation (especially on scala 2.12).
So we wonder:
Is scala-async library ready for production?
Is it meant to be used as a general approach or should it be used careful just for complex async cases?
How much impact does it have on compilation time?
How much impact does it have on size of generated byte code?
Does it have any performance issues?

Is scala-async library ready for production?

Yes, I would say this is true. We work closely with one user that has deployed it widely.

Is it meant to be used as a general approach or should it be used careful just for complex async cases?

This is really a style issue that depends on your tastes. In general, some control flow patterns are easier to express with async, so there would be a stronger argument to use it for those ones. Some people prefer the consistent approach of also using async for cases where for comprehesions / flatMap would have similar readibility.

How much impact does it have on compilation time?

We don't have data on this, but it is an area that we're plan to investigate this year.

How much impact does it have on size of generated byte code?

async translate all the logic into a single class, rather than each continution into a separate function. In Scala 2.11, this typically reduces bytecode size. It also reduces runtime allocations of functions. In Scala 2.12, the bytecode for each of the functions is translated into a method, and the anon function class is created at link time with invokedynamic. Internally in the JVM, the representation is the same, but if you're just looking at the contents of JAR files, the function-based approach would appear more compact than in 2.11.

Does it have any performance issues?

One thing we're aware of is that for complex async blocks, we end up generating the code in one large method. This might exceed the threshold for the JVM to JIT compile, which could hurt performance. However, the cost of interpreting code might not be important compared to the cost of context switching in Future. Another improvement we're planning is to have a mode where the code for each state of the state machine is wrapped in a single private method, which would make things more JIT friendly.

We did some tests on the library but found out that it produce much more java byte code then map/flatMap does in the same in the same situation (especially on scala 2.12).

Could you share a self-contained example of this that we could discuss concretely?

Thank you for the answers. It helps a lot.