We’ve spent the last few weeks porting the Aeron client from Java to .NET.
What is Aeron?
Aeron is a high speed message transport. It allows messages to be sent over the network via UDP (unicast or multicast) or between processes via IPC in shared memory.
Aeron is the brainchild of Martin Thompson and Todd Montgomery. Martin was the co-founder and CTO of LMAX and is a high-performance specialist. Todd was CTO of 29West where he was the chief designer of their low latency messaging products. They’ve been working on Aeron over the past 2 years and have just released version 1.0.
It is made up of clients and a media driver. The clients encode/decode messages and pass them to the media driver which runs in its own process and is responsible for sending and received messages over the network. The clients communicate with the media driver through shared memory using lock-free algorithms.
As well as the C# client, there are also clients written in Java and C++.
Show me some numbers
At the time of writing, when using C# Aeron client and the Java media driver, it is capable of sending and receiving about 30 million messages per second. We used HDRHistogram.Net to measure latency by measuring the roundtrip time of a message. 99% of messages roundtrips are under 25 microseconds. You can check these numbers yourself by running the media driver with the IpcThroughput sample and the Ping and Pong samples.
Once it’s up and running, it does not allocate any memory which means that latency is more predictable because no time is spent garbage collecting.
Show me some code
There is a full Hello World example here. Here’s a breakdown of the most important parts.
Publisher
The client connects to the media driver and instructs it to prepare a publisher which will send messages to another media driver listening on UDP port 40123. Messages can be split into different streams and sent to the same channel.
string channel = "aeron:udp?endpoint=localhost:40123"; int streamId = 42; Aeron aeron = Aeron.Connect() Publication publication = aeron.AddPublisher(channel, streamId);
Creating a message
Part of the reason Aeron is able to achieve such high throughput is by not creating objects when sending messages. Instead of newing up a DTO, Aeron uses byte arrays to represent messages. UnsafeBuffer is a wrapper that has methods for writing various types.
UnsafeBuffer buffer = new UnsafeBuffer(new byte[256]); buffer.PutStringWithoutLengthUtf8(0, “Hello World!”);
Sending a message
To send the message, just pass the message buffer along with the offset at which the message starts and the length of the message to the publisher.
publisher.Offer(buffer, 0, message.Length);
Subscriber
The next code fragment sets up a subscription, it causes the media driver to listen on the endpoint defined by channel, in this case udp://localhost:40123 and pick up messages sent to the relevant streamId. You pass it a message handler (which will be explained in the next section) and a fragment limit which defines the maximum number of fragments to process in one poll.
Subscription subscription = aeron.AddSubscription(channel, streamId); subscription.Poll(messageHandler, fragmentLimitCount); // see messageHandler below
Processing a message
The FragmentHandler defines what happens to messages that are received by a subscription. In this case, we know the message consists of a string so we can read it out directly. For more complex scenarios, for instance when messages might be too large and need to be split up, a FragmentAssembler can be used to reassemble the message.
FragmentHandler messageHandler = (buffer, offset, length, header) => { Console.WriteLine(buffer.GetStringWithoutLengthUtf8(offset, length)); };
Where can I get it?
The Aeron client is available from NuGet.
PM> Install-Package Aeron.Client
Alternatively, the source code is up on GitHub:
https://github.com/AdaptiveConsulting/Aeron.NET/
You can also get a copy of the Java driver through NuGet:
PM> Install-Package Aeron.Driver
What’s Next?
We will continue to work on the code keeping it up to date with changes to the official Java version, fixing bugs and improving performance where we can. We need early adopters to pick up the code and start playing around.
Author:
James Watson