Saterday I was talking to Jonas Boner of the Akka project, which uses Multiverse as STM implementation. Since Multiverse 0.4 doesn’t support static instrumentation and the Akka project doesn’t want to rely on a Javaagent, in Multiverse 0.3 a manual instrumented reference was added. I never spend any time optimizing it, so I decided to have a closer inspection since the Akka project relies on it.
One of the biggest performance gains was for reading a value from a transactional reference without an existing transaction, this went op from 7.5M transactions/second to 160M transactions/second using a single thread. The main part of this improvement was the inlining of the transaction and the transactiontemplate. This reduces object creation and makes a ref.get() almost just as expensive as a AtomicReference.get. So developers should not be worried about using that instead of an AtomicReference if they also are working with transactions.
Another performance improvement, although less spectacular, was on writing a value to a transactional reference using its own transaction, that went up from 5M to 12M transactions per seconds on a single thread. This was also mostly caused by inlining the transaction. I already have experimented with reducing the number of cas operations and pushing it to 15M is possible. So I’m looking at how to integrate that. The goal is that Multiverse can have the performance of CAS for CAS transactions but also can participate in fullblown transactions (that are of course more expensive and therefore slower).
Inlining the transaction certainly is something that is going to be add to the other instrumentation optimizations in the future (every release I try to add a few). The improved manual instrumented reference (AlphaRef) is going to be added to the 0.4.2 release planned for this week (somehow still struggling with the maven release plugin). It also is going to gain some other goodies like an optimistic lock that can be used spanning multiple transactions (comparable to what you normally do with optimistic locking using a database).
For the 0.4.3 release I’ll add a history of dynamic length to the manual instrumented reference (in Oracle this is done using the undolog and in Clojure this functionality is called “adaptive history queues”) to give Jonas his persistent datastructures. This is a present of the Multiversion Concurrency Control design which makes this possible (essentially TL2 is MVCC with a single length history). For Multiverse I’m planning a persistent history queue, where you even have control on the number of old versions that need to be maintained, but sadly enough not planned for the 0.5 release (I also have a full-time job).