In this article we list the main reasons that make CoralFIX a very fast and easy to use FIX engine.
- Network I/O: The most important part of a FIX engine in terms of performance is the network I/O library. That’s because FIX parsing can be done in nanoseconds while TCP latencies are in microseconds. So it is not enough to be super fast when parsing the FIX message while your bottleneck may be in the network I/O. In addition to parsing a FIX message very fast (in nanoseconds), CoralFIX uses CoralReactor under the hood, which brings years of our experience with Java NIO and network I/O. We provide our own selector implementation which is 10 times faster than the standard JDK implementation.
- Zero Garbage: All Coral Blocks components produce zero garbage for the GC in the critical path. With CoralFIX you are able to send/receive billions of messages without ever producing any garbage. No GC interruption, ever!
- Zero Depedencies: At Coral Blocks we use Java as a syntax language. Our libraries have zero external dependencies and we don’t even rely on the JDK standard libraries. With CoralFIX you have total control over the critical path.
- Zero Copy: When parsing a ByteBuffer into a FixMessage object, CoralFIX does not copy any bytes or create any objects. The resulting FixMessage object is backed up by the same ByteBuffer that was parsed. The parsing process simply delimits the tags and values of the FIX message. Moreover all values are lazy parsed, in other words, a price value won’t be parsed to a double until you explicitly call getDouble(FixTags.Price). Or you can call getByteBuffer(FixTags.Price) to return your value delimited in the original ByteBuffer, without any parsing.
- Thread Affinity: Although not a requirement, it is recommended that you pin your critical threads to dedicated cpu cores. CoralFIX supports thread affinity out-of-the-box and can pin your critical threads to the cpu cores you specify. To pin your critical threads, all you have to do is pass the cpu core id in the command-line options below:
-DnioReactorProcToBind=CORE_ID -DlogProcToBindAsyncThread=CORE_ID -DfixStoreProcToBind=CORE_ID
NioReactor nio = NioReactor.create(); MapConfiguration config = new MapConfiguration(); config.add("fixVersion", FixVersions.VERSION_44); config.add("senderComp", "testClient"); Client client = new FixApplicationClient(nio, "localhost", 45451, config); client.open(); nio.start();
// add a start session timer daily at 14:30:00 EST config.add("startSessionTimer", "D-EST-14:30:00"); // add a stop session timer weekly on Sunday at 16:00:00 EST config.add("stopSessionTimer", "W-SUNDAY-EST-16:00:00");
// Get a FIX message ready to be sent out, with sequences, header and everything taken care for you FixMessage outFixMsg = getOutFixMessage(MsgTypes.NewOrderSingle); // Add any kind of value as a tag outFixMsg.add(Price, 50.34); outFixMsg.add(ClOrdID, "A123"); outFixMsg.add(Side, '2'); // Add a repeating group FixGroup partyIds = outFixMsg.createGroup(NoPartyIDs); partyIds.nextElement().add(PartyID, "BLAH").add(PartyIDSource, 'D').add(PartyRole, 54); partyIds.nextElement().add(PartyID, "TRD").add(PartyIDSource, 'D').add(PartyRole, 36); // Send out the message to the client send(outFixMsg);
tcpdumpand Wireshark to measure the tick-to-trade latencies and they are around 8 micros.
Although it is important for a FIX engine to be as fast as possible, and we got that covered through fast parsing and networking, at Coral Blocks we believe that ease of use is even more important. Not just CoralFIX but all of our components must be very easy to understand, integrate and use. Our licensing model also allows us to have a commitment to our clients in providing first-class support and to share our know-how throughout the license period. We are passionate about what we do and we enjoy working side-by-side with our clients to bring outstanding results.