This is the eighth of several posts describing the evolution of scala.concurrent.Future
in Scala 2.12.x
.
For the previous post, click here.
Goodbye, sun.misc.Unsafe
A Future
can be seen as a tri-state1 state machine with the following distinct states:
- Uncompleted
- Completed with a successful result
- Completed with a failed result
In order to have an «asynchronous Future» it is vital to be able to register logic to be executed once the Future
becomes Completed.
This means that we can encode the state 1
as a «sequence of callbacks & their ExecutionContext
», state 2
as a scala.util.Success
, and state 3
as a scala.util.Failure
.
Given that, we only need to have a single var
in our Future
-implementation, which will either be a Seq
, a Success
or a Failure
.
Since Future
can both be completed and have new callbacks added concurrently we need to be able to access this var
atomically, so simply making it @volatile
won’t be enough: we need Compare-And-Set semantics.
The first Akka Future
which served as the main implementation inspiration for SIP-14, it used an inner field of type AtomicReference
.
In the initial scala.concurrent.Future
design, instead of taking the cost of having to allocate an extra object for the AtomicReference
and take the cost for that indirection, we used what’s known as an AtomicReferenceFieldUpdater
(ARFU).
Now, from a Scala perspective there are 2 problems with ARFUs: 1. They require the use of static fields—which Scala does not support, and, 2. They are about 10-20% slower than sun.misc.Unsafe
access.
Since performance is always important in the Standard Library, we changed to use sun.misc.Unsafe
for the implementation of scala.concurrent.Future
and be OK with it requiring us to have a base-class in Java with a static field to hold the memory address offset of the field.
But! For 2.12.x we decided to take a «better» way, which eliminates the need for static fields and sun.misc.Unsafe
:
We have now completely replaced the use of sun.misc.Unsafe
for DefaultPromise
(the internal implementation of the Scala Standard Library Promises) with extending AtomicReference
internally, this means that there is no need for a base-class in Java and no need for ARFUs or sun.misc.Unsafe
.
Benefits
- The same, excellent, performance as previously
- With much better platform compatibility and security
1: In practice it turns out to be a four-state state machine due to the feature of «Promise Linking», we’ll cover that topic in the next post.
Click here for the next part in this blog series.
Cheers,
√