Thursday 11 April 2013

Release of Disruptor 3.0.0

I've decided that I'm a bit bored of the whole putting a beta tag on various versions of the Disruptor so I've decide to send forth Disruptor 3.0.0 into the world. The big challenges of this release were to clean up the code and come up with a better algorithm for handling multiple producers. If I was lucky, make it even faster. I went down a couple of dark alleys initially with this release, but have come up again for air with a version that is less different to the 2.x version, but still brings some nice benefits.  I had wanted to implement a few more functional tests and improve the documentation, but I could be waiting forever to those aspects to a level where I was 100% satisfied.


Improved Support for Multiple Producers

One of the really nasty problems with the 2.x version of the Disruptor is that it came with 2 implementations of the ClaimStrategy.  One was for the situations where there was more threads than CPUs and one for when there was less.  This was a little bit ugly.  Version 3 now has a single MultiProducerSequencer (more on Sequencers/ClaimStrategies later) that should work well in both cases.  It is a bit slower for the un-contended case that our previous implementation around 18M ops/sec v 15M ops/sec*, but should scale much better as the number of threads increased and exceeds the CPU count.  I did a couple of talks about the new implementation at TechMesh and JAX London last year.  If you are interested in the specifics of the algorithm a YouTube video of the JAX London talk is available.


No More Claim Strategies

One of the major changes to the internal design and API is that I have gotten rid of the ClaimStrategy interface.  With some of the changes that I wanted to make to the multiple producer use case it got cumbersome.  So I deleted it and instead provide 2 implementations of the Sequencer, SingleProducerSequencer and MultiProducerSequencer that covers the 2 important use cases.  We no longer allow users to plug-in their own implementation, sorry about that, but the code became much cleaner, simpler and faster as a result.


Faster for the Single Producer Case

The one producer to one consumer benchmark* shows around 220M ops/sec for version 3 compared to 80M ops/sec for version 2.  This has been mostly the result of general clean up (e.g. removing ClaimStrategies) and a few small optimisations.


Improved EventTranslator API for the RingBuffer

The EventTranslator API that the RingBuffer now supports now has variants for 1, 2, 3 and Varargs parameters to be passed through to the EventTranslator implementation.  This means that input into the EventTranslator doesn't have to be done via an anonymous inner class or pushing values through fields in the EventTranslator implementation.  It also makes it easier to write EventTranslators as independent units that can be easily tested.  Code isolation FTW!


Batch Producer Interface for the Sequencer

I wasn't a big fan of our existing batch producer interface and initially I'd intended to dump it.  After some thought I've added it partially back in.  I.e. it is only available on the Sequencer.  I may add it to the RingBuffer at a later point if I can come up with a clean safe API to expose the functionality.  Out of interest I added a raw sequencer throughput test that uses the batch interface.  This test does no real work, it just signals between the threads.  However I have proved that the Disruptor can do nothing useful, in batches of 10 at more that 4 000 000 000 ops/sec.  Not a useful benchmark in any case, but great for the bragging rights!


Special Mentions

There were a few people that helped out getting the Disruptor from is version 2 state to version 3:
  • Jason Koch: Manned up and did a huge amount of JavaDoc.  I've been trying to keep it up to date since I merged his pull request.
  • Dalibor Novak and Danny Yates: Github and Gradle migration.
  • Adrian Sutton: Further work on the DSL.
  • Martin Thompson: For his many useful ideas, especially around the algorithm to support multiple producers.
It is now available from Maven Central and the Github download page.

*All tests done on my Intel Core i7-3770 (Ivy Bridge) @ 3.40 GHz - YMMV.

6 comments:

Trevor Bernard said...

Awesome stuff! Looking forward to giving it a test drive.

Unknown said...

Good to see it released. Thanks for the mention.

John said...

Congrats on v3. Have been watching this project from a distance for a while. Finally ready to start experimenting. Suggestions on the best place to start? Use case is replacing an existing (api-only) service running on Tomcat.

Michael Barker said...

@John

Personally I wouldn't start by trying to apply the Disruptor to your project straight away. First make sure that you have a good clean design where your concurrency is handled by passing messages between threads and you understand where your producers and consumers are. If you have that, then the Disruptor should fit in naturally.


If you are just looking to experiment, then there is a couple of examples floating around.

Nitin S said...

The Git URL for master is eventually timing out during cloning:

https://github.com/LMAX-Exchange/disruptor.git

I was trying to get version 3.1.1. Direct download as zip is also failing. Can you please check ??

Michael Barker said...

It's working fine for me.