Saturday 1 September 2012

Disruptor utility

At LMAX, we use the Disruptor in lots of places within our codebase. Usages vary, but one pattern that has been repeated is the use of a Disruptor to serialise multi-threaded access to a non-thread-safe resource (following the single-writer principle).

The approach we've used has always seemed a little clunky, though it has been sufficient for our needs. The general pattern follows this approach:

Given an interface:

we will write an interface that puts messages into a ring-buffer:

the EventHandler then dispatches to the correct method on the actual implementation object:

This approach works well enough, but can be quite verbose if the interface in question has many methods or long parameter lists. We've used it so far because we haven't had any of those problems.

While working on a side-project, I wanted to use the Disruptor to serialise access to an object that had a slightly more complex interface. After starting down the road described above, I realised that the problem could be solved for the general case with a little byte-code generation.

disruptor-proxy is a small library designed to handle all the boiler-plate involved in the described approach. Using the example above, it is trivial to create a proxy object backed by a ring-buffer:

Two types of generator are supported: BYTECODE_GENERATION and JDK_REFLECTION, which should be self-explanatory. Using the byte-code generation method will add a dependency on the Javassist library.

The performance difference between to the two methods was not as great as I had expected it to be. Reflection doesn't seem to be anywhere near as expensive as it used to be:

Tests performed on Intel(R) Core(TM) i7-2670QM CPU @ 2.20GHz
[JDK_REFLECTION] - Ops per second: 14461091.00, avg latency 69ns
[BYTECODE_GENERATION] - Ops per second: 18313904.00, avg latency 54ns