Version 1.0.0
One of the ways to ensure the highest possible performance and quality of software products is to run stress/load tests. This article describes how we do the load testing of our high-performance .NET Core FIX Engine.
The test harness consists of two projects – Initiator and Acceptor. The Initiator establishes the FIX Sessions and sends one million FIX messages, and the Acceptor receives these messages. After that, we measure how long it took Initiator to send one million FIX messages and how long it took Acceptor to receive these messages.
We send FIX messages between two machines that have the following configuration:
Initiator connects to Acceptor and establishes the FIX Session:
initiator.LogonAsInitiator(host, port, heartBeatInterval);
The Initiator sends 10000 warmup messages and waits for the reply on the Test Request message as the confirmation that Acceptor received all sent messages using the Session.SendTestRequest method:
const int NumberOfWarmupMessages = 10000;
for (var i = 0; i < NumberOfWarmupMessages; ++i)
initiator.Send(order);
initiator.SendTestRequest("Warmup is finished", TimeSpan.FromMinutes(5));
The Initiator sends one million New Order Single FIX messages (150 bytes each) and waits until Acceptor receives all messages:
var sendStart = Stopwatch.GetTimestamp();
const int NumberOfMessages = 1000000;
for (var i = 0; i < NumberOfMessages; ++i)
initiator.Send(order);
var sendFinish = Stopwatch.GetTimestamp();
initiator.SendTestRequest("Testing is finished", TimeSpan.FromMinutes(5));
The Acceptor receives one million orders and measures throughput on receiving side:
acceptor.InboundSessionMessage += (object sender, InboundMessageEventArgs args) =>
{
Message message = args.Message;
if (message.CompareType(OnixS.Fix.Fix42.MsgType.Test_Request))
{
if (message.Get(OnixS.Fix.Fix42.Tag.TestReqID) == "Warmup is finished")
{
receiveStart = Stopwatch.GetTimestamp();
}
else if (message.Get(OnixS.Fix.Fix42.Tag.TestReqID) == "Testing is finished")
{
receiveFinish = Stopwatch.GetTimestamp();
ReportRecevingThroughput(receiveStart, receiveFinish);
}
}
};
static void ReportRecevingThroughput(long receiveStart, long receiveFinish)
{
var receiveMessagesPerSec = Stopwatch.Frequency * NumberOfMessages / (receiveFinish - receiveStart);
WriteLine($"The throughput on the receiving side: {string.Format("{0:n0}", receiveMessagesPerSec)} msg/sec.");
}
Initiator terminates the connection and reports the throughput:
initiator.Logout();
var sendMessagesPerSec = Stopwatch.Frequency * NumberOfMessages / (sendFinish - sendStart);
WriteLine($"The throughput on the sending side: {string.Format("{0:n0}", sendMessagesPerSec)} msg/sec.");
The test run gives us the following results:
The throughput on the sending side: 2,274,190 msg/sec. The throughput on the receiving side: 1,808,499 msg/sec.
So, sending one million FIX New Order Single messages took 0.44
sec.