LibHFTDocumentationMicrobenchmarks

Inside the FIX codec

FIX codec microbenchmarks.

Measure the work behind each message: parsing, reading fields and constructing FIX messages. Compare all six LibHFT flavors with their language peers in one qualified, in-process benchmark campaign.

25 licensed adapters6 LibHFT flavorsBatch-average ns / operationQualified · HP · 18 October 2026

Explore the results

One message. Every operation.

Choose a FIX message and compare encoding, checked parsing and parsing + extraction together for every language. Each table is ranked by measured p50 within its language and operation.

Campaign: HP · Intel Xeon Gold 6254 · Linux 5.14.0-687.44.1.el9_8.x86_64 · measurement CPUs 16–17; launcher CPUs 0–7 · 18 October 2026 · measured LibHFT source 5917330b7c2c. Peer versions and pinned inputs are listed under method and evidence.

NewOrderSingle · 25 measured adapters · 73 operation results. Lower is better.

Compare p50 and p99 at a glance. Expand CDF & all percentiles for the top-five-engine chart and the full ranked table. Missing results are labelled, never plotted as zero.

See the NewOrderSingle message and all three tests →

Percentiles are rounded batch-average nanoseconds per operation: each of the 50,000 samples averages 32 in-process operations, so they are not individual-call or network latencies. CDFs connect measured percentile anchors; they are reconstructed profiles, not raw-sample empirical CDFs. What each test measures →

Same-host codec comparison

C++ and C

Native FIX engines and codec libraries, including LibHFT C++, QuickFIX/C++, NexusFIX, Fix8, hffix, Fixpp, llfix and libtrading. llfix encoding is ranked here; its receive cells include SDK timestamp, sequence and callback work and are listed separately.

Encoding

Field values → FIX bytes

NewOrderSingle · encoding · ns/operation
Engine / codecp50p99
LibHFT C++4950
hffix127132
llfix321328
NexusFIX363380
libtrading445457
QuickFIX/C++2,6142,624
Fix83,0653,088
Fixpp3,0883,145
CDF & all percentiles
LibHFT C++hffixllfixNexusFIXlibtrading
Reconstructed CDF of the fastest 5 qualifying engines by p50
Percentile-anchor reconstruction, not a raw-sample empirical CDF. Up to five engines with matching evidence; the table retains the full roster. Open CDF ↗
NewOrderSingle · encoding · ns/operation · ranked by p50
RankEngine / codecp50 (ns)p90 (ns)p99 (ns)p99.9 (ns)
1LibHFT C++49505051
2hffix127130132133
3llfix321324328330
4NexusFIX363371380388
5libtrading445451457461
6QuickFIX/C++2,6142,6202,6242,627
7Fix83,0653,0763,0883,097
8Fixpp3,0883,1103,1453,172
How this test works →

Checked parsing

FIX bytes → checked field values

NewOrderSingle · checked parsing · ns/operation
Engine / codecp50p99
LibHFT C++356358
hffix389397
NexusFIX849856
Fixpp919922
libtrading1,4791,484
QuickFIX/C++2,0952,103
Fix85,5195,538
llfixReceive includes SDK timestamp, sequence and callback work · listed separately, unranked
CDF & all percentiles
LibHFT C++hffixNexusFIXFixpplibtrading
Reconstructed CDF of the fastest 5 qualifying engines by p50
Percentile-anchor reconstruction, not a raw-sample empirical CDF. Up to five engines with matching evidence; the table retains the full roster. Open CDF ↗
NewOrderSingle · checked parsing · ns/operation · ranked by p50
RankEngine / codecp50 (ns)p90 (ns)p99 (ns)p99.9 (ns)
1LibHFT C++356358358359
2hffix389394397397
3NexusFIX849854856858
4Fixpp919920922924
5libtrading1,4791,4821,4841,486
6QuickFIX/C++2,0952,0992,1032,105
7Fix85,5195,5305,5385,546
—llfixReceive includes SDK timestamp, sequence and callback work · listed separately, unranked
How this test works →

Parsing + extraction

FIX bytes → extracted business fields

NewOrderSingle · parsing + extraction · ns/operation
Engine / codecp50p99
LibHFT C++356358
hffix387395
NexusFIX852861
Fixpp918921
libtrading1,4791,484
QuickFIX/C++2,0932,100
Fix85,5115,529
llfixReceive includes SDK timestamp, sequence and callback work · listed separately, unranked
CDF & all percentiles
LibHFT C++hffixNexusFIXFixpplibtrading
Reconstructed CDF of the fastest 5 qualifying engines by p50
Percentile-anchor reconstruction, not a raw-sample empirical CDF. Up to five engines with matching evidence; the table retains the full roster. Open CDF ↗
NewOrderSingle · parsing + extraction · ns/operation · ranked by p50
RankEngine / codecp50 (ns)p90 (ns)p99 (ns)p99.9 (ns)
1LibHFT C++356357358359
2hffix387392395397
3NexusFIX852857861863
4Fixpp918920921923
5libtrading1,4791,4821,4841,486
6QuickFIX/C++2,0932,0972,1002,102
7Fix85,5115,5215,5295,536
—llfixReceive includes SDK timestamp, sequence and callback work · listed separately, unranked
How this test works →

Same-host codec comparison

Java

Java Pure and Java/JNI beside QuickFIX/J, Philadelphia, Artio and Falcon. JNI timing includes one native codec call per message.

Encoding

Field values → FIX bytes

NewOrderSingle · encoding · ns/operation
Engine / codecp50p99
Philadelphia3081,564
LibHFT Java Pure347627
LibHFT Java/JNI3921,014
Falcon8871,199
Artio1,1692,269
QuickFIX/J1,3465,008
CDF & all percentiles
PhiladelphiaLibHFT Java PureLibHFT Java/JNIFalconArtio
Reconstructed CDF of the fastest 5 qualifying engines by p50
Percentile-anchor reconstruction, not a raw-sample empirical CDF. Up to five engines with matching evidence; the table retains the full roster. Open CDF ↗
NewOrderSingle · encoding · ns/operation · ranked by p50
RankEngine / codecp50 (ns)p90 (ns)p99 (ns)p99.9 (ns)
1Philadelphia3083111,5641,741
2LibHFT Java Pure3475356272,625
3LibHFT Java/JNI3924971,0141,201
4Falcon8879201,1994,965
5Artio1,1691,2722,26923,957
6QuickFIX/J1,3461,3755,0085,656
How this test works →

Checked parsing

FIX bytes → checked field values

NewOrderSingle · checked parsing · ns/operation
Engine / codecp50p99
LibHFT Java Pure5851,179
LibHFT Java/JNI7101,353
Falcon7432,766
Philadelphia9792,104
QuickFIX/J1,6294,265
Artio1,9953,869
CDF & all percentiles
LibHFT Java PureLibHFT Java/JNIFalconPhiladelphiaQuickFIX/J
Reconstructed CDF of the fastest 5 qualifying engines by p50
Percentile-anchor reconstruction, not a raw-sample empirical CDF. Up to five engines with matching evidence; the table retains the full roster. Open CDF ↗
NewOrderSingle · checked parsing · ns/operation · ranked by p50
RankEngine / codecp50 (ns)p90 (ns)p99 (ns)p99.9 (ns)
1LibHFT Java Pure5855871,1791,259
2LibHFT Java/JNI7107151,3531,410
3Falcon7437472,7664,904
4Philadelphia9799852,1045,239
5QuickFIX/J1,6291,6634,2657,834
6Artio1,9952,5363,869384,320
How this test works →

Parsing + extraction

FIX bytes → extracted business fields

NewOrderSingle · parsing + extraction · ns/operation
Engine / codecp50p99
LibHFT Java Pure583593
LibHFT Java/JNI710722
Falcon743767
Philadelphia9811,025
QuickFIX/J1,6301,722
Artio1,9962,081
CDF & all percentiles
LibHFT Java PureLibHFT Java/JNIFalconPhiladelphiaQuickFIX/J
Reconstructed CDF of the fastest 5 qualifying engines by p50
Percentile-anchor reconstruction, not a raw-sample empirical CDF. Up to five engines with matching evidence; the table retains the full roster. Open CDF ↗
NewOrderSingle · parsing + extraction · ns/operation · ranked by p50
RankEngine / codecp50 (ns)p90 (ns)p99 (ns)p99.9 (ns)
1LibHFT Java Pure583585593649
2LibHFT Java/JNI710713722781
3Falcon743746767914
4Philadelphia9819861,0251,240
5QuickFIX/J1,6301,6391,7221,998
6Artio1,9962,0102,0812,410
How this test works →

Same-host codec comparison

.NET

.NET Pure and .NET Native beside QuickFIX/n and the public FIX Antenna .NET Core codec. The native flavor includes its interop boundary.

Encoding

Field values → FIX bytes

NewOrderSingle · encoding · ns/operation
Engine / codecp50p99
LibHFT .NET Pure191985
LibHFT .NET Native265539
FIX Antenna .NET Core2,58310,503
QuickFIX/n4,78218,952
CDF & all percentiles
LibHFT .NET PureLibHFT .NET NativeFIX Antenna .NET CoreQuickFIX/n
Reconstructed CDF of the fastest 4 qualifying engines by p50
Percentile-anchor reconstruction, not a raw-sample empirical CDF. Up to five engines with matching evidence; the table retains the full roster. Open CDF ↗
NewOrderSingle · encoding · ns/operation · ranked by p50
RankEngine / codecp50 (ns)p90 (ns)p99 (ns)p99.9 (ns)
1LibHFT .NET Pure1919629851,011
2LibHFT .NET Native265526539549
3FIX Antenna .NET Core2,5832,63110,50314,034
4QuickFIX/n4,7824,81118,95222,481
How this test works →

Checked parsing

FIX bytes → checked field values

NewOrderSingle · checked parsing · ns/operation
Engine / codecp50p99
LibHFT .NET Native5011,812
LibHFT .NET Pure1,0042,662
FIX Antenna .NET Core1,6513,161
QuickFIX/n4,9877,334
CDF & all percentiles
LibHFT .NET NativeLibHFT .NET PureFIX Antenna .NET CoreQuickFIX/n
Reconstructed CDF of the fastest 4 qualifying engines by p50
Percentile-anchor reconstruction, not a raw-sample empirical CDF. Up to five engines with matching evidence; the table retains the full roster. Open CDF ↗
NewOrderSingle · checked parsing · ns/operation · ranked by p50
RankEngine / codecp50 (ns)p90 (ns)p99 (ns)p99.9 (ns)
1LibHFT .NET Native5015031,8121,932
2LibHFT .NET Pure1,0041,0072,6622,864
3FIX Antenna .NET Core1,6511,6703,1614,416
4QuickFIX/n4,9875,0237,3347,756
How this test works →

Parsing + extraction

FIX bytes → extracted business fields

NewOrderSingle · parsing + extraction · ns/operation
Engine / codecp50p99
LibHFT .NET Native484486
LibHFT .NET Pure1,0211,029
FIX Antenna .NET Core1,6481,690
QuickFIX/n4,9817,291
CDF & all percentiles
LibHFT .NET NativeLibHFT .NET PureFIX Antenna .NET CoreQuickFIX/n
Reconstructed CDF of the fastest 4 qualifying engines by p50
Percentile-anchor reconstruction, not a raw-sample empirical CDF. Up to five engines with matching evidence; the table retains the full roster. Open CDF ↗
NewOrderSingle · parsing + extraction · ns/operation · ranked by p50
RankEngine / codecp50 (ns)p90 (ns)p99 (ns)p99.9 (ns)
1LibHFT .NET Native484485486487
2LibHFT .NET Pure1,0211,0251,0291,035
3FIX Antenna .NET Core1,6481,6651,6904,264
4QuickFIX/n4,9815,0157,2917,676
How this test works →

Same-host codec comparison

Rust

LibHFT Rust, FerrumFIX, DFX, fixer-rs, TrueFix and NanoFIX under the same message fixtures and measured operations.

Encoding

Field values → FIX bytes

NewOrderSingle · encoding · ns/operation
Engine / codecp50p99
LibHFT Rust144145
NanoFIX168171
FerrumFIX1,2711,311
TrueFix1,6341,648
fixer-rs3,8113,826
DFX5,8155,862
CDF & all percentiles
LibHFT RustNanoFIXFerrumFIXTrueFixfixer-rs
Reconstructed CDF of the fastest 5 qualifying engines by p50
Percentile-anchor reconstruction, not a raw-sample empirical CDF. Up to five engines with matching evidence; the table retains the full roster. Open CDF ↗
NewOrderSingle · encoding · ns/operation · ranked by p50
RankEngine / codecp50 (ns)p90 (ns)p99 (ns)p99.9 (ns)
1LibHFT Rust144144145146
2NanoFIX168170171172
3FerrumFIX1,2711,2901,3111,321
4TrueFix1,6341,6441,6481,651
5fixer-rs3,8113,8193,8263,839
6DFX5,8155,8405,8626,009
How this test works →

Checked parsing

FIX bytes → checked field values

NewOrderSingle · checked parsing · ns/operation
Engine / codecp50p99
LibHFT Rust527539
NanoFIX1,2481,256
TrueFix2,0362,042
DFX2,5382,547
fixer-rs4,6744,686
FerrumFIX7,4227,450
CDF & all percentiles
LibHFT RustNanoFIXTrueFixDFXfixer-rs
Reconstructed CDF of the fastest 5 qualifying engines by p50
Percentile-anchor reconstruction, not a raw-sample empirical CDF. Up to five engines with matching evidence; the table retains the full roster. Open CDF ↗
NewOrderSingle · checked parsing · ns/operation · ranked by p50
RankEngine / codecp50 (ns)p90 (ns)p99 (ns)p99.9 (ns)
1LibHFT Rust527533539544
2NanoFIX1,2481,2521,2561,260
3TrueFix2,0362,0392,0422,044
4DFX2,5382,5442,5472,549
5fixer-rs4,6744,6804,6864,689
6FerrumFIX7,4227,4387,4507,461
How this test works →

Parsing + extraction

FIX bytes → extracted business fields

NewOrderSingle · parsing + extraction · ns/operation
Engine / codecp50p99
LibHFT Rust528544
NanoFIX1,2301,248
TrueFix2,0362,043
DFX2,6562,674
fixer-rs4,6114,624
FerrumFIX7,4257,460
CDF & all percentiles
LibHFT RustNanoFIXTrueFixDFXfixer-rs
Reconstructed CDF of the fastest 5 qualifying engines by p50
Percentile-anchor reconstruction, not a raw-sample empirical CDF. Up to five engines with matching evidence; the table retains the full roster. Open CDF ↗
NewOrderSingle · parsing + extraction · ns/operation · ranked by p50
RankEngine / codecp50 (ns)p90 (ns)p99 (ns)p99.9 (ns)
1LibHFT Rust528537544550
2NanoFIX1,2301,2391,2481,256
3TrueFix2,0362,0402,0432,045
4DFX2,6562,6682,6742,678
5fixer-rs4,6114,6194,6244,627
6FerrumFIX7,4257,4437,4607,470
How this test works →

Same-host codec comparison

Go

QuickFIX/Go is retained in the wider codec roster. There is no LibHFT Go flavor and no same-language competitor ranking to infer from this single row.

Encoding

Field values → FIX bytes

NewOrderSingle · encoding · ns/operation
Engine / codecp50p99
QuickFIX/Go8,128182,531
CDF & all percentiles
QuickFIX/Go
Reconstructed CDF of the fastest 1 qualifying engines by p50
Percentile-anchor reconstruction, not a raw-sample empirical CDF. Up to five engines with matching evidence; the table retains the full roster. Open CDF ↗
NewOrderSingle · encoding · ns/operation · ranked by p50
RankEngine / codecp50 (ns)p90 (ns)p99 (ns)p99.9 (ns)
1QuickFIX/Go8,12813,063182,531498,344
How this test works →

Checked parsing

FIX bytes → checked field values

NewOrderSingle · checked parsing · ns/operation
Engine / codecp50p99
QuickFIX/Go2,4054,637
CDF & all percentiles
QuickFIX/Go
Reconstructed CDF of the fastest 1 qualifying engines by p50
Percentile-anchor reconstruction, not a raw-sample empirical CDF. Up to five engines with matching evidence; the table retains the full roster. Open CDF ↗
NewOrderSingle · checked parsing · ns/operation · ranked by p50
RankEngine / codecp50 (ns)p90 (ns)p99 (ns)p99.9 (ns)
1QuickFIX/Go2,4054,4364,63784,929
How this test works →

Parsing + extraction

FIX bytes → extracted business fields

NewOrderSingle · parsing + extraction · ns/operation
Engine / codecp50p99
QuickFIX/Go2,4014,650
CDF & all percentiles
QuickFIX/Go
Reconstructed CDF of the fastest 1 qualifying engines by p50
Percentile-anchor reconstruction, not a raw-sample empirical CDF. Up to five engines with matching evidence; the table retains the full roster. Open CDF ↗
NewOrderSingle · parsing + extraction · ns/operation · ranked by p50
RankEngine / codecp50 (ns)p90 (ns)p99 (ns)p99.9 (ns)
1QuickFIX/Go2,4014,4364,65059,625
How this test works →

Listed separately · C++

llfix receive results, unranked.

The llfix 1.0.8 receive path is measured through the upstream LLFIX_BENCHMARK hook, without SDK patches or a substitute parser. That hook enters FixClient::process_rx_buffer, which reads the monotonic clock, updates the sequence store and dispatches the callback for every message. Those costs are inside each sample, so these six cells stay outside the codec rankings. SDK receive validations and serialization are disabled for this lane. Its three encoder cells, which include the SDK-generated SendingTime, are ranked in the C++ tables above.

Swipe the table horizontally for all percentiles.

llfix receive · HP · 18 October 2026 · rounded batch-average ns/operation
Message · operationp50p90p99p99.9
NewOrderSingle · Checked parsing1,4691,4771,4811,485
NewOrderSingle · Parsing + extraction1,4741,4851,4891,495
ExecutionReport · Checked parsing1,7411,7471,7531,758
ExecutionReport · Parsing + extraction1,7561,7611,7661,769
MarketDataSnapshot · depth 10 · Checked parsing4,9574,9644,9684,972
MarketDataSnapshot · depth 10 · Parsing + extraction9,0349,1039,1319,154

An earlier single-engine llfix run on SCAN (3 October 2026, source 211372a6) remains historical evidence with its own summary CSV, field probes, host qualification, source and checksum receipt, measurement clock, CPU configuration and snapshot. It is not merged with this campaign.

What the test measures

Three operations. Shared messages.

WRITE

Encoding

Start with field values, populate a message and serialize it through the public builder. Framing and checksum work are included only where that adapter’s build path performs them.

PARSE

Checked parsing

Parse and check the complete business-field set for D/8. For W, check symbol, entry count and best bid/offer. Numeric conversion and the typed value hash are inside timing.

READ

Parsing + extraction

Parse, read the specified business fields and fold them into a checked sink. Depth-10 market data includes all 20 ordered bid/offer entries.

Fixtures are NewOrderSingle (35=D), ExecutionReport (35=8) and a 10-level MarketDataSnapshot (35=W). The same pinned fixtures and sample counts are used throughout.

See the actual FIX messages and a worked explanation of all nine tests →

Codec cost is not deployed FIX latency.

The ranked cells exclude networking, Logon, sequence recovery, storage and application callbacks. llfix’s receive cells include its SDK callback and are listed separately, unranked. There is no offered messages-per-second target in this in-process test, and the inverse of a codec timing is not sustained session capacity. Use the full-engine comparison for that question.

From bytes to measured work

What happens in each test?

The corrected converted-values-v2 contract requires complete checked field work for both D/8 parse labels. They intentionally perform the same operation; neither is a framing-only shortcut. W distinguishes top-of-book checks from full-book extraction. Build starts from values, not by parsing or echoing the input message.

Swipe diagrams sideways on a small screen, or open a diagram to zoom.

Checked parse: receive bytes, verify the required fields.

Parse-only operation
Pinned bytes enter the public parser. D and 8 check the complete converted business-field set; W checks top of book. The typed value hash is checked inside each operation. One clock sample covers 32 repeated operations. Open diagram ↗

Parse and extract: the reads are inside the sample.

Parse-and-extract operation
Parse the pinned message, convert and hash the full common field set. D checks nine fields; 8 checks twelve; W checks all 20 entries in order. For D/8 the two parse labels now perform the same checked work. One timed sample batches 32 operations. Open diagram ↗

Build: start from values, not a received message.

Message-building operation
Start from field values, populate the public builder, serialize and consume output length. Framing depends on the adapter. One timed sample batches 32 complete build operations. Open diagram ↗

In the examples, | represents the real FIX separator SOH (ASCII 0x01). Line breaks are for readability only. Restore SOH and remove those line breaks to recover the pinned input bytes; BodyLength (9) and CheckSum (10) are calculated for those bytes.

Tags 9001 and 9002 are benchmark-specific field-work hashes, not standard FIX fields or cryptographic signatures. The oracle uses type-marked converted values: unsigned integers, scale-five fixed-point prices and ASCII strings, each followed by byte 1. The fixed July timestamps belong to the fixtures, not the October measurement date. Download the pinned examples and their source hashes.

NewOrderSingle · 35=D

A day limit order to buy 100,000 AUD/NZD at 1.08245. 11 is the client order ID, 55 the symbol, 54=1 buy, 38 quantity, 40=2 limit, 44 price and 59=0 day time-in-force.

Pinned input for both parsing tests

8=FIX.4.2|9=161|35=D|49=CLIENT|56=SERVER|34=8|52=20260703-19:28:00.123|
11=ORD123456|21=1|55=AUD/NZD|54=1|60=20260703-19:28:00.123|38=100000|40=2|44=1.08245|59=0|9002=2863910631|
10=021|
1. Checked parse parse_only
Feed the complete order into the public parser and read all nine fields: 11, 21, 55, 54, 60, 38, 40, 44, 59. Convert numeric values, fold typed values into FNV-1a and compare with 9002=2863910631. No order is submitted and no session state changes.
2. Parse and extract parse_extract
Perform the same complete checked operation as D parse_only. Both names remain for table compatibility, not as different amounts of field work. Text and numeric mutations independently verify each operation's reads.
3. Build build_D
Populate an order with the business values above through the public builder, serialize its fields and consume the output length. Sequence numbers or generated client order IDs may change between iterations. This measures constructing an order, not transmitting it or obtaining an execution.
Sample build payload · header and framing omitted
35=D|
11=ORD123456|21=1|55=AUD/NZD|54=1|60=20260703-19:28:00.123|38=100000|40=2|44=1.08245|59=0|

An illustrative payload assembled from the fixture’s business values, not a captured byte-for-byte result from every builder.

ExecutionReport · 35=8

An acknowledgement that the order is new, with all 100,000 units still open: 150=0 is a new execution event, 39=0 new order status, 151=100000 remaining quantity, 14=0 filled quantity and 6=0.00000 average fill price. This is not a fill report.

Pinned input for both parsing tests

8=FIX.4.2|9=193|35=8|49=CLIENT|56=SERVER|34=9|52=20260703-19:28:00.123|
37=EX123456|17=EXRPT1|11=ORD123456|150=0|39=0|55=AUD/NZD|54=1|38=100000|151=100000|14=0|6=0.00000|60=20260703-19:28:00.123|9002=564350835|
10=162|
1. Checked parse parse_only
Parse and perform the same complete twelve-field checked operation described below. It does not update an order book or position.
2. Parse and extract parse_extract
Parse, read and hash twelve values: order ID (37), execution ID (17), client order ID (11), execution type (150), order status (39), symbol (55), side (54), order quantity (38), remaining quantity (151), filled quantity (14), average price (6) and transaction time (60). The typed hash includes converted quantities and fixed-point price. Compare it with 9002=564350835; mismatches count as errors.
3. Build build_8
Set those twelve business fields and the message header, serialize through the public builder and retain the output length. The receive-side 9002 audit marker is not part of this build payload. Execution IDs, sequence numbers and field order may vary by adapter.
Sample build payload · header and framing omitted
35=8|
37=EX123456|17=EXRPT1|11=ORD123456|150=0|39=0|55=AUD/NZD|54=1|38=100000|151=100000|14=0|6=0.00000|60=20260703-19:28:00.123|

The report’s business fields without the receive-side audit marker; not a captured wire result from every builder.

Market data snapshot · 35=W

A ten-level AUD/NZD book: ten bids and ten offers, each sized at 1,000,000. 268=20 counts entries, not levels. Each entry contains side (269=0 bid or 269=1 offer), price (270) and size (271). Best bid/offer are 1.08241 / 1.08245.

Complete pinned input · all twenty entries, with one bid/offer pair per display line

8=FIX.4.2|9=723|35=W|49=CLIENT|56=SERVER|34=10|52=20260703-19:28:00.123|
262=REQ-AUDNZD-1|55=AUD/NZD|268=20|
269=0|270=1.08241|271=1000000|269=1|270=1.08245|271=1000000|
269=0|270=1.08240|271=1000000|269=1|270=1.08246|271=1000000|
269=0|270=1.08239|271=1000000|269=1|270=1.08247|271=1000000|
269=0|270=1.08238|271=1000000|269=1|270=1.08248|271=1000000|
269=0|270=1.08237|271=1000000|269=1|270=1.08249|271=1000000|
269=0|270=1.08236|271=1000000|269=1|270=1.08250|271=1000000|
269=0|270=1.08235|271=1000000|269=1|270=1.08251|271=1000000|
269=0|270=1.08234|271=1000000|269=1|270=1.08252|271=1000000|
269=0|270=1.08233|271=1000000|269=1|270=1.08253|271=1000000|
269=0|270=1.08232|271=1000000|269=1|270=1.08254|271=1000000|
9001=2376139772|9002=2366019821|10=214|
1. Parse only parse_only
Give the complete depth-ten message to the parser. Read symbol (55), entry count (268) and the first two prices (270), then compare their typed converted-value hash with 9001=2376139772. This is a top-of-book check, not extraction of all twenty entries.
2. Parse and extract parse_extract
Parse, read request ID (262), symbol and entry count, then visit all twenty entries in wire order. Read each entry’s side, price and size: 60 group values plus the three leading values. Convert and hash them, then compare with 9002=2366019821. Reading only the first bid/offer pair cannot satisfy this check.
3. Build build_W
Set request ID and symbol, create 268=20 and write the ten bid/offer pairs, then serialize and retain the output length. The payload contains the full book, not a two-entry shortcut. Receive-side audit tags 9001 and 9002 are omitted. Falcon W is unsupported: upstream Falcon has no market-data message model, so these three cells are not measured for it.
Sample build payload · all twenty entries, header and framing omitted
35=W|
262=REQ-AUDNZD-1|55=AUD/NZD|268=20|
269=0|270=1.08241|271=1000000|269=1|270=1.08245|271=1000000|
269=0|270=1.08240|271=1000000|269=1|270=1.08246|271=1000000|
269=0|270=1.08239|271=1000000|269=1|270=1.08247|271=1000000|
269=0|270=1.08238|271=1000000|269=1|270=1.08248|271=1000000|
269=0|270=1.08237|271=1000000|269=1|270=1.08249|271=1000000|
269=0|270=1.08236|271=1000000|269=1|270=1.08250|271=1000000|
269=0|270=1.08235|271=1000000|269=1|270=1.08251|271=1000000|
269=0|270=1.08234|271=1000000|269=1|270=1.08252|271=1000000|
269=0|270=1.08233|271=1000000|269=1|270=1.08253|271=1000000|
269=0|270=1.08232|271=1000000|269=1|270=1.08254|271=1000000|

The complete book payload without receive-side audit tags; not a captured wire result from every builder.

Read build timings at the adapter’s actual boundary.

Builders need not emit identical bytes: IDs, field order, FIX version and number formatting can differ. Most paths finish a framed FIX message; the pinned Java Pure path times header/body serialization without final 8/9/10 framing. That row is not a measurement of a completed on-wire message.

How the separate mutation checks prove field work

These are admission checks, not extra latency rankings. The harness mutates a field while keeping the message’s length and FIX checksum valid, but leaves the expected value hash stale. An adapter passes the probe only when it reports the hash mismatch.

  • Report extraction: change 37=EX123456 to 37=FX123356. The 9002 check must detect the changed order ID.
  • Full-book extraction: change the second level’s prices from 1.08240 / 1.08246 to 1.08250 / 1.08236. The best bid/offer stay unchanged; the full 9002 check must notice the deeper entries.
  • Top-of-book check: change 55=AUD/NZD to 55=BUD/NYD. The selected W parse_only operation must detect the stale 9001 value; rejection by a different operation cannot satisfy the probe.
  • Numeric conversion: change the order price from 44=1.08245 to 44=1.08254, or the last book size from 271=1000000 to 271=0100000. These preserve framing but change the converted value and must fail the selected operation’s hash check.

All 332 isolated text/numeric probes pass in the 25-adapter HP campaign. Each supported D/8/W parsing operation must reject its own mutation with a positive error count and exit code 3; rejection by another operation cannot satisfy it. Falcon has eight D/8 probes and llfix twelve receive-field probes; LibHFT C++ adds probes for its cursor and legacy entrypoints, which are diagnostic and not displayed. This is field-work evidence, not full FIX conformance or network performance.

Comparison boundaries

A missing cell is not a measurement.

The page shows each adapter’s default entrypoint for D, 8 and depth-10 W: encoding, checked parsing and parsing + extraction. Cursor, legacy and other diagnostic variants are excluded from these tables.

  • Falcon W is unsupported. Falcon has D and 8 results only; selecting market data shows it as not supported, without timings or a rank.
  • llfix receive is unranked. Its six receive cells include SDK timestamp, sequence and callback work, so they are listed separately. Its three encoder cells are ranked.
  • libtrading depth-10 W uses the retained 128-field capacity patch.
  • FerrumFIX uses the pinned v0.7.0 shim.
  • LibHFT Java Pure build timing covers header and body serialization without final 8/9/10 framing.

Other non-admitted, unsupported or licence-excluded targets are not shown. Their absence here is not evidence of slower performance. JMH runs, llfix reference transport tests and full-session results are separate evidence, outside this codec table.

The page shows 216 ranked D/8/W codec cells and six unranked llfix receive cells. The campaign’s summary CSV retains all 560 operation rows, including administrative messages and the C++ cursor/legacy variants, without mixing those paths into the default ranking.

Recorded methodology

One host. Frozen inputs. Audited windows.

HostHP · Intel Xeon Gold 6254 · Linux 5.14.0-687.44.1.el9_8.x86_64 · measurement CPUs 16–17; launcher CPUs 0–7. Hardware epoch record
Campaign date18 October 2026. This is a pinned codec snapshot, not an assertion about every later release or every deployment.
Measured sourceLibHFT 5917330b7c2c7d67d01eea58379eca00bd5389bb; later publishing revisions do not change it
Methodconverted-values-v2: 50,000 timed samples after 5,000 warm-up samples per operation; 32 operations per clock sample
Admission25/25 build/run gates, 332/332 extraction mutation probes, 560 operation rows and a complete clock contract
Host qualificationPassing 120-second quiet-host preflight before each of four audited segments; five-second all-PID monitor; no competing samples at or above 5% CPU in any selected adapter window
SelectionFour segments with the same source, prepared runtimes, fixtures, CPU affinity and sample counts. Contaminated windows were excluded, not averaged into the ranking.

The mutation audit changes wire-valid fields while leaving their expected field hash stale. A passing probe rejects the mismatch, demonstrating that the adapter reads the required fields rather than merely accepting a fixed message.

Peer versions and pinned inputs

Versions are shown where the campaign evidence records one. Other peers are identified by the SHA-256 of the pinned source tree or jar that was compiled and measured; the prepared manifest lists every input.

Measured versions and pinned inputs · HP · 18 October 2026
AdapterRecorded versionPinned input · SHA-256 prefix
LibHFT .NET NativeLibHFT source 5917330b7c2cMeasured source above
LibHFT .NET PureLibHFT source 5917330b7c2cMeasured source above
LibHFT C++LibHFT source 5917330b7c2cMeasured source above
LibHFT Java PureLibHFT source 5917330b7c2cMeasured source above
LibHFT Java/JNILibHFT source 5917330b7c2cMeasured source above
LibHFT RustLibHFT source 5917330b7c2cMeasured source above
Artio0.178artio-codecs-0.178.jar · d4eff79c0958
DFXNot version-labelled in the evidencedfx · a20c4e0933f8
FalconNot version-labelled in the evidencefalcon-0.1.0-master-SNAPSHOT.jar · fc2085cee1a2
FerrumFIXv0.7.0 shimferrumfix · b381f8e4273a
FIX Antenna .NET CoreNot version-labelled in the evidencefixantenna_net · c4c4ad326f9f
Fix8Not version-labelled in the evidencefix8/include · 2c895eb218f9
fixer-rsNot version-labelled in the evidencefixer_rs · 2cde38c9dc45
FixppNot version-labelled in the evidencefixpp/include · 448c4879c106
hffixNot version-labelled in the evidencehffix/include · 398621473830
libtradingNot version-labelled in the evidencelibtrading/include · 175aca29e54d
llfix1.0.8llfix/include · 8b81571731fc
NanoFIXNot version-labelled in the evidencenanofix · c7b7e48898be
NexusFIXNot version-labelled in the evidencenexusfix/include · 896323421dac
Philadelphia2.0.0philadelphia-core-2.0.0.jar · 396136037b0f
QuickFIX/C++Not version-labelled in the evidencequickfix_cpp/include · a1a5402cc254
QuickFIX/GoNot version-labelled in the evidencequickfix_go · f7cc9f36cefa
QuickFIX/J2.3.1quickfixj-core-2.3.1.jar · d063713127ae
QuickFIX/nNot version-labelled in the evidencequickfix_n · 91bd60612128
TrueFixNot version-labelled in the evidencetruefix · 3c64f5be84a2

Summary CSV SHA-256: dfda98a2cd6d288c44bda4666966ea4941611d2d9f59f78db01576c1a314366c. Prepared manifest SHA-256: 62b830d8b3d7ea45af627c6bb1257b2a92a103e11eec58d6b2c6aeb20692f1ac. Host qualification SHA-256: f63aae7a540c9ec65c7e9c2d41bcf9cda45cbda1c4bb75b1e6e710d629096422. Compact result set SHA-256: ace4e77ba182a372d90e086e287b96deaec65ba78ced16dbc90c647df2148ec4. Prepared manifest · machine-readable snapshot.

Reproduce the pinned measurement procedure

Use the measured source revision, prepared-manifest digest and peer pins above. Preparation and timing are separate; reserve the host CPU slot and review process activity before publishing a result.

python3 bench/cpp/fixbench/tools/open_source_fix_engines/open_source_fix_engine_stage2.py \
  --workspace "$LIBHFT_BUILD_ROOT/stage2-workspace" \
  --run-prepared --parity-audit --run-cpus 16,17 \
  --iterations 50000 --warmup 5000

This command requires the previously prepared, hash-verified workspace; it is not a standalone installation command. Another host joins this comparison only after its own qualification with matching inputs.

Historical campaign

The earlier SCAN campaign (Intel Xeon E5-2698 v4, isolated CPUs 18–19, 2–3 October 2026) measured the same 25 adapters with LibHFT source 4375a8fe and different peer pins: 320 probes and 554 operation rows. It is retained as historical evidence and is not merged into these rankings.