4. INTRODUCTION
High Performance Inter-Thread Messaging Library
LMAX build the system on the JVM platform and
centers on a Business Logic Processor that can
handle 6 million orders per second on a single
thread with very low latency: 100K TPS with 1 ms
latency.
Multicast events to consumers, with consumer
dependency graph.
Pre-allocate memory for events.
Optionally lock-free.
8. MEMORY BARRIERS
A type of barrier instruction that causes a central
processing unit (CPU) or compiler to enforce an
ordering constraint on memory operations issued
before and after the barrier instruction.
9. CACHE LINE
Unit of transfer between memory and CPU
Cache-Lines size is (typically) 64 bytes.
10. FALSE SHARING
When a system participant attempts to periodically
access data that will never be altered by another
party, but that data shares a cache block with data
that is altered, the caching protocol may force the
first participant to reload the whole unit despite a
lack of logical necessity.
11. FALSE SHARING
struct foo { int x; int y; };
static struct foo f;
/* The two following functions are running concurrently: */
int sum_a() {
int s = 0;
int i;
for (i = 0; i < 1000000; ++i)
s += f.x;
return s;
}
void inc_b() {
int i;
for (i = 0; i < 1000000; ++i)
++f.y;
}
21. CUSTOM EVENTHANDLER
...
public class Data {
public string Value { get; set; }
}
public class DataEventHandler : IEventHandler<Data>
{
public string Name { get; private set; }
public DataEventHandler(string name) {
this.Name = name;
}
public void OnEvent(Data data, long sequence, bool endOfBatch) {
Console.WriteLine("Thread = {0}, Handler = {1}, Sequence = {2}, Value
= {3}", Thread.CurrentThread.ManagedThreadId.ToString(), this.Name,
sequence, data.Value);
}
}
...
22. DSL
Generate disruptor
instance with factory
method and ring buffer
size
Setup consumer
dependency graph with
Disruptor.HandleEvents
With
Start disruptor with
Disruptor.Start
Get ring buffer
Get next ring buffer
sequence
Set data
Publish data
23. DSL
...
var disruptor = new Disruptor.Dsl.Disruptor<Data>(() => new Data(), (int)Math.Pow(2,4),
TaskScheduler.Default);
disruptor.HandleEventsWith(new DataEventHandler("Handler1"));
var ringBuffer = disruptor.Start();
var sequenceNo = ringBuffer.Next();
var data = ringBuffer[sequenceNo];
data.Value = "Hello";
ringBuffer.Publish(sequenceNo);
sequenceNo = ringBuffer.Next();
data = ringBuffer[sequenceNo];
data.Value = "World";
ringBuffer.Publish(sequenceNo);
disruptor.Shutdown();
...
24. NON-DSL
Generate ring buffer with
factory method and ring
buffer size
Setup consumer
dependency graph with
EventProcessor And
Barrier
Start EventProcessor in
another thread
Get next ring buffer
sequence
Set dataPublish data
25. NON-DSL
...
var ringBuffer = RingBuffer<Data>.CreateSingleProducer(() => new Data(), (int)Math.Pow(2, 4));
var barrier = ringBuffer.NewBarrier();
var eventProcessor = new BatchEventProcessor<Data>(ringBuffer, barrier, new DataEventHandler("Handler1"));
Task.Factory.StartNew(() => eventProcessor.Run());
var sequenceNo = ringBuffer.Next();
var data = ringBuffer[sequenceNo];
data.Value = "Hello";
ringBuffer.Publish(sequenceNo);
sequenceNo = ringBuffer.Next();
data = ringBuffer[sequenceNo];
data.Value = "World";
ringBuffer.Publish(sequenceNo);
eventProcessor.Halt();
Application.DoEvents();
...
26. UNICAST: 1P - 1C
...
using Disruptor;
namespace ConsoleApplication29 {
…
class Program {
static void Main( string[] args) {
var disruptor = new Disruptor.Dsl. Disruptor<Data>(() => new Data(), (int)Math .Pow(2,4),
TaskScheduler.Default);
disruptor.HandleEventsWith(new DataEventHandler("Handler1”));
var ringBuffer = disruptor.Start();
var idx = 0;
while ( true) {
var sequenceNo = ringBuffer.Next();
var data = ringBuffer[sequenceNo];
data.Value = idx++.ToString();
ringBuffer.Publish(sequenceNo);
Thread.Sleep(250);
}
disruptor.Shutdown();
}
}
} P1 C1
27. UNICAST: 1P - 1C
...
var ringBuffer = RingBuffer<Data>.CreateSingleProducer(()
=> new Data(), (int)Math.Pow(2, 4));
var barrier = ringBuffer.NewBarrier();
var eventProcessor = new
BatchEventProcessor<Data>(ringBuffer, barrier, new
DataEventHandler("Handler1"));
Task.Factory.StartNew(() => eventProcessor.Run());
...
eventProcessor.Halt();
...
P1
Barrier
C1