Measure your Disruptor.net performance with Disruptor-net.Metrics

10. januar 2016

Measure your Disruptor.net performance with Disruptor-net.Metrics

When you go into production with a project which is utilizing the disruptor framework, it's really nice to know what's going on when the software is running. Is data coming through? Is running slow? How much of the ringbuffer is available? These are some of the common questions I have heard over the time.

So, I have written a small metrics package which hooks up nicely into the disruptor pattern and serves relevant metrics.

This post will cover:

 

Install

Get the latest from nuget:

PM> Install-Package Disruptor-net.Metrics

Or get the source from github: https://github.com/ThomasVestergaard/Disruptor-net.Metrics

 

Hook it up - 3 steps.

The metrics package works by adding a timestamp on events right before it's enqueued. Then we add a eventhandler after all of your existing eventhandlers which will do the actual processing and reporting.

You can either follow this guide or get a complete example here: https://github.com/ThomasVestergaard/Disruptor-net.ThroughPutDemo

 

1. What ever you put in your ringbuffer, make it implement IRingBufferItem.

public class QueueItem : IRingBufferItem
{
    public DateTimeOffset FirstTouchTime { get; set; }
    // All your other stuff here
    public void Update(QueueItem other)
    {
      ...
    }
}

 

2. When you enqueue a new item, set FirstTouchTime to UtcNow

public void Enqueue(QueueItem item)
{
    var next = ringBuffer.Next();
    var entry = ringBuffer[next];
    entry.Update(item);
    entry.FirstTouchTime = DateTimeOffset.UtcNow;
    ringBuffer.Publish(next);
}

 

3. Add the metrics eventhandler to your disruptor.

var metricsEventHandler = new FixedSecondCountReporter<QueueItem>(new ColoredConsoleSink(), 1);    
disruptor = Disruptor<QueueItem>(() => new QueueItem(), ringbufferSize, TaskScheduler.Default);
disruptor.HandleEventsWith(eventHandler1, eventHandler2).Then(metricsEventHandler);
ringBuffer = disruptor.Start();
metricsEventHandler.Setup(ringBuffer); // Important: Do this AFTER disruptor.Start() has been run.

 

FixedMessageCountReporter vs. FixedSecondCountReporter

There are two options on how to get the metrics reported. Chosing which, depends on what you want to do with the metrics afterwards.

It's important to understand that both methods use the incoming events to trigger the reporting. That means if no messages are coming through the disruptor, no metrics will be reported.

Important: FixedSecondCountReporter has a bigger performance overhead than FixedMessageCountReporter.

 

Sinks

If you are familiar with the Serilog logging framework, you already know what sinks are.

Sinks are where the metrics object is dumped once either FixedSecondCountReporter or FixedMessageCountReporter reports. This gives you a endpoint to hook up your favorite logging framework for further processing.

The Disruptor-net.Metrics nuget packages comes with a ColoredConsoleSink which outputs metrics to the console. Useful for debugging but not production.

You can also get the Disruptor-net.Metrics.Sinks.Serilog nuget package to get metrics into serilog.

Or you can make your own by simply implementing ISink:

public class MyVeryOwnSink : ISink
{
    public void ReportMetrics(IRingbufferPerformanceMetrics metrics)
    {
        // Create you own handler here. Remember it's blocking the processing thread.
    }
}