Libfabric provider matrix over 100 Gb/s

Goblin Core's fastest locally available network path completed Redis-shaped operations in 6.39 microseconds at the arithmetic-average median. That was SBE over libfabric FI_EP_RDM using verbs;ofi_rxm and the automatic inject path. The same eight operations averaged 90.33 microseconds over ordinary kernel TCP with RESP2: 14.1x higher latency and 14.0x fewer sequential round trips per second.

Libfabric's software tcp provider also mattered. RESP2 over that provider averaged 39.59 microseconds at p50, 2.28x lower than RESP2 over the kernel socket path. This is a provider and software-path result, not a bandwidth result; every workload deliberately used pipeline depth one.

Scope: this qualifies the Goblin code path intended for AWS EFA, but it is not an AWS EFA hardware result. Native provider efa was unavailable on the local machines. The measured providers were tcp and verbs;ofi_rxm on a pair of 14-year-old, four-socket Intel Xeon E5-4657L v2 systems over a direct 100 Gb/s Mellanox ConnectX-5 Ethernet link. The native AWS EFA fast follow is now published.

Complete ranking

Modes are ranked by the arithmetic average of the eight per-operation medians. The average p99.99 is likewise an average of reported per-operation percentiles, not a merged distribution. Sequential operations per second is the reciprocal of each operation's observed mean, averaged across operations.

Rank Transport/provider Wire Send path Avg p50 (us) Avg mean (us) Avg seq. ops/s Avg p99.99 (us) Worst max (us)
1 verbs;ofi_rxm SBE auto-inject 6.39 6.51 156,498 30.83 952.81
2 verbs;ofi_rxm SBE fi_send 6.67 6.69 152,576 30.64 995.31
3 verbs;ofi_rxm RESP2 auto-inject 7.38 7.56 134,388 32.31 973.51
4 verbs;ofi_rxm RESP2 fi_send 7.69 7.80 130,176 32.63 983.07
5 libfabric tcp SBE fi_send 38.12 38.48 26,268 76.80 200.13
6 libfabric tcp SBE auto-inject 39.09 39.48 26,014 77.05 218.95
7 libfabric tcp RESP2 auto-inject 39.59 40.17 25,084 73.73 217.58
8 libfabric tcp RESP2 fi_send 39.82 40.19 25,075 75.47 204.38
9 Kernel TCP SBE kernel send 61.71 62.62 16,079 116.17 1,127.29
10 Kernel TCP RESP2 kernel send 90.33 91.34 11,170 151.82 2,358.18

SBE over verbs;ofi_rxm led the aggregate result with either send path. Automatic injection was 4.2-4.4% faster at the average median than forced fi_send on that provider, while their average p99.99 results differed by less than one percent. On the software tcp provider, the two send policies were effectively tied.

The forced-send result is important beyond its ranking: every frame used fi_send, transmit buffers were reclaimed through the TX completion queue, receives used fi_recv, and receive completions came through fi_cq_readfrom. The faster automatic mode uses fi_inject for an eligible small frame and falls back to that same fi_send path for a larger frame.

Operation latency

Each cell below is p50 / p99.99 in microseconds. Pub/Sub measures the full path from issuing PUBLISH, through its acknowledgement, to validated receipt by one literal-channel subscriber.

Automatic inject path

Kernel TCP is included as the socket baseline; "automatic" applies only to the libfabric columns.

Operation Kernel TCP / RESP2 Kernel TCP / SBE libfabric tcp / RESP2 libfabric tcp / SBE verbs;ofi_rxm / RESP2 verbs;ofi_rxm / SBE
PING 63.74 / 99.58 55.06 / 99.83 36.36 / 64.66 34.57 / 67.76 5.65 / 26.34 4.73 / 25.33
SET 94.07 / 215.54 62.08 / 183.27 39.77 / 94.03 36.86 / 89.76 7.63 / 54.00 6.34 / 52.31
GET 86.84 / 130.38 57.58 / 102.74 37.69 / 64.65 35.09 / 68.34 6.51 / 28.93 6.22 / 26.24
HSET 96.89 / 165.96 66.41 / 108.31 39.97 / 73.38 38.97 / 68.70 8.33 / 30.80 7.60 / 29.34
HGET 89.14 / 157.82 58.52 / 102.41 37.79 / 67.64 35.08 / 66.38 7.12 / 28.87 5.59 / 26.38
ZADD 98.95 / 147.30 66.70 / 113.62 40.03 / 70.25 38.78 / 71.87 8.32 / 31.36 7.09 / 29.94
ZSCORE 88.40 / 138.30 56.89 / 99.68 36.67 / 64.72 34.90 / 69.42 7.03 / 26.31 6.23 / 26.97
PUBSUB 104.60 / 159.69 70.47 / 119.51 48.41 / 90.50 58.43 / 114.18 8.44 / 31.86 7.30 / 30.09

The tcp/SBE automatic Pub/Sub cell was slower than its RESP2 neighbor and than the forced-SBE result. It is retained as measured rather than replaced by an inferred value.

Forced fi_send path

Operation libfabric tcp / RESP2 libfabric tcp / SBE verbs;ofi_rxm / RESP2 verbs;ofi_rxm / SBE
PING 35.78 / 73.07 34.45 / 76.37 6.36 / 27.17 5.46 / 24.92
SET 39.81 / 92.30 36.90 / 90.60 7.84 / 54.27 6.76 / 53.02
GET 37.69 / 73.31 36.56 / 70.21 7.10 / 28.92 6.09 / 25.45
HSET 39.95 / 73.13 38.46 / 80.59 8.44 / 31.00 7.92 / 28.98
HGET 37.83 / 67.17 36.10 / 68.21 7.33 / 28.67 6.12 / 27.38
ZADD 41.28 / 73.05 38.85 / 69.53 9.00 / 31.08 7.89 / 28.48
ZSCORE 37.72 / 68.96 34.81 / 65.96 6.70 / 27.99 5.58 / 26.46
PUBSUB 48.48 / 82.74 48.82 / 92.94 8.72 / 31.92 7.53 / 30.47

The raw matrix on GitHub contains min, p50, p75, p90, p95, p99, p99.9, p99.99, maximum, mean, and sequential operations per second for all 80 distributions. Its neighboring README records the build identity and artifact layout.

Tail behavior

On verbs;ofi_rxm, operation-level p99.99 ranged from 24.92 to 54.27 microseconds across both wire formats and send paths. Isolated maxima between 0.74 and 1.00 milliseconds remained beyond p99.99. Kernel TCP produced the largest single observation, 2.36 milliseconds during GET.

The original RDM qualification had a much larger and repeatable tail step. It was not caused by out-of-order delivery. Instrumented depth-one runs observed 1,760,003 replies on the publisher connection and 220,001 replies on the subscriber connection without one sequestered frame, duplicate, reorder-window overflow, sequence gap, or pending reordered message. Server-side request counters were likewise clean.

The stall was local to Goblin's bootstrap listener. The polled server called nonblocking accept() on every spin-loop pass. On Linux, an unsuccessful accept() can allocate and then retire socket, file, and inode objects before returning EAGAIN. Function tracing showed repeated RCU softirq batches that reclaimed those objects, with individual batches lasting roughly 0.4-1.1 milliseconds.

Goblin now checks listener readiness first and only drains accept() when a bootstrap connection is waiting. Before the fix, one trace contained 4,119 RCU softirq runs over 100 microseconds. During a two-second active post-fix trace, all 59 softirq runs were below 100 microseconds and the maximum was 20.6 microseconds. The immediate control run cut average SBE/RDM p99.99 from 857.47 to 29.47 microseconds; this independent full matrix reproduced it at 30.83 microseconds.

The preserved pre-fix results and traces are in benchmarks/libfabric-2026-07-26.

Method

Depth-one operations per second measure sequential round trips, not saturated throughput. The 100 Gb/s link is a latency path in this test, not a bandwidth target.

Reproduction

The complete cross-host matrix is automated:

SAMPLES=200000 WARMUP=20000 \
  bash benchmarks/libfabric_provider_matrix.sh

An automatic-inject server for the fastest local provider:

build/goblin-core \
  --libfabric 'verbs;ofi_rxm' 10.100.0.1 17401 \
  --enable-sbe \
  --no-auth-libfabric \
  --efa-heartbeat-timeout-ms 0 \
  --cpu 5 \
  --numa 1

Add --libfabric-force-send to route every frame through fi_send and its TX completion queue. The benchmark executable selects the same client-side mode with the final auto or send argument:

numactl --physcpubind=5 --membind=1 \
  build/goblin_core_libfabric_latency_benchmark \
  fabric-sbe 'verbs;ofi_rxm' 10.100.0.1 17401 10.100.0.2 \
  verbs-sbe-send 200000 20000 send