A 10 nanosecond messaging hop means little beneath a 7 microsecond decode-and-book floor. Maciejewski measures the actor abstraction at under 1% of that floor, which comes from SBE decode and book mutation rather than message delivery. The decomposition survives scrutiny. The broader HFT claim has a tighter boundary, one the paper identifies before anyone else can. Its abstract ends "A saturated-throughput and contention evaluation is left to future work."

The suitability case for an HFT hot path therefore depends on a live feed where the mailbox ring was empty for 87% to 99.7% of messages, alongside microbenchmarks that keep one message in flight.

We could not reproduce any of it. These measurements require raw CME MDP 3.0 multicast packets, socket-level timestamps, and an order book built in C++ on pinned cores. Our finest data consists of 1-minute OHLCV bars, which cannot test either fast_send or tick-to-book latency. The discussion below reads Maciejewski's figures and considers the choices they leave an implementer.

What fast_send changes

The canonical actor model sends each message through the receiver's mailbox. That path entails heap allocation, enqueue, dequeue, scheduler dispatch, context switch, then the same sequence for the reply.

fast_send strips away that route. The sender's thread acquires the receiver's exclusive-access lock, executes the receiver's handler inline, and returns the reply as a value. Receiver transparency keeps the mechanism within the actor model. Both modes use identical handler code. The handler cannot detect the delivery mode, the executing thread, or whether the sender is blocked. Both also heap-allocate the reply deliberately, preventing allocation side effects from revealing the mode. Before lock acquisition, a thread-local call chain detects cyclic invocation and stops the thread from wedging itself.

Three related mechanisms accompany it. Actor groups place a set of actors on one thread behind a shared mailbox. Every actor chooses its own mailbox from four MPSC implementations. A fixed-size memory pool replaces new/delete for messages whose lifetime extends beyond the call.

The survey stands on its own. Looking across Erlang, Akka, Orleans, CAF, SObjectizer, Actix, Pony, Swift and Ray, Maciejewski finds no runtime that executes the receiver's handler on the sender's thread. He also challenges the usual prior: on Savina, CAF ran only about 1.09x ahead of Akka at 20 threads and trailed it on nine of sixteen benchmarks.

About 10 ns per hop, versus 1 ns directly

The microbenchmark ladder keeps the work constant while restoring one operation at each row. It measures a ping/pong round trip with a reply on an AMD EPYC 9374F, using two pinned cores and the median of three runs. A cross-thread asynchronous send between actors on separate cores takes roughly 3370 ns at the median. Grouping both actors on one thread retains the queue while removing the thread hop, cutting the result 37x to 90 ns. Replacing that queue with inline fast_send brings the round trip to about 30 ns.

The paper reports that row as total wall time over N operations. With a steady_clock tick of about 10 ns, each sample's percentile is resolution-bound. The result is roughly 110x faster than the ungrouped path and 3x faster than the grouped path.

One hop takes about 10 ns. A bare devirtualized direct call costs about 1 ns under the same measurement. The paper therefore assigns the framework about 10 ns per hop beyond the direct call. That 10 ns pays for receiver-lock acquisition and release, message-field setup, handler-cache dispatch, and reply wrapping.

For a grouped round trip with two allocations, the pool lowered amortized cost from about 128 ns to about 92 ns. A separate run cut the maximum round trip from 5.5 ms to 33 us. Two orders of magnitude on the figure that matters at p99.9.

One throughput result cuts against intuition, as Maciejewski observes. Drain-side batching raised asynchronous throughput from 5.5 to 8.96 million round trips per second. Adding the pool pushed it to 13.6 million, about 74 ns per message. Sender-side batching reduced throughput to 11.3 million because producer and consumer became serialized, eliminating their overlap.

Batching belongs only on the drain side.

Can the 7 us floor survive live CME traffic?

The live sample contains 8.29 million messages from ES, NQ and ZN book and trade streams. It covers 53 minutes on 2026-09-16, on one machine. Each message receives two software timestamps. Maciejewski states explicitly that t0 occurs at the socket read, making this a socket-to-book measurement that excludes NIC and kernel time. No hardware receive timestamps were taken.

Median latency follows a simple model: a floor plus a slope multiplied by the message's position within its packet. The fit uses medians at queue length zero. Across the six fitted intercepts, one for each stream, values range from 6.81 to 7.23 us. The spread is 0.42 us, and every observation is a message first in its packet. Three estimators built differently place the book floor within about 0.4 us of one another. During an FOMC release, packet rates jumped 4.6 to 9.8x within a second. The floor shifted by at most +0.4 us and fell for two of three instruments.

The hot path shows no rate sensitivity.

A 10 ns hop amounts to about a seventh of one percent against that floor. The paper estimates the entire collapsed decode/book/signal chain at a few tens of nanoseconds, still well under 1%. Nobody counted the fast_send hops in the live path, however. Each implementer must count the hops in their own path.

The slope carries the engineering value. It runs from 312 ns/msg on NQ book to 966 ns/msg on ZN book. Without hardware counters, Maciejewski cannot divide that 3x spread between cache residency and a heavier message mix. The last message in a 45-message packet incurs roughly 25 us above the floor, deterministically. Across the trade streams, 99.3 to 99.6% of messages have another message ahead of them in the same packet. Any reduction in slope benefits a message according to its position, directly targeting the tail.

Queue backlog creates the other tail, rare and convex. With an empty ring, ES book has a 6.9 us median; at six queued packets, it reaches 16.6 us. ZN book reaches 21.7 us at five. Yet qlen at or above 3 appears on 0.08% of ES book messages, 2,311 out of 2,861,519, while 87% to 99.7% of all messages encounter an empty ring.

The missing saturation test

Every microbenchmark measures sequential latency with one message in flight. Chain depth and contention remain fixed, a limitation the paper states in four places, including the abstract. It matters because fast_send keeps the receiver's lock throughout the handler and blocks the caller. Concurrent synchronous senders aimed at a hot actor will serialize on that lock.

The paper works through this and gives two escape routes. fast_send_x is non-blocking and raises ActorBusy; fast_send_void falls back to the mailbox. It further proposes the ratio of synchronous completions to fallbacks as a signal of contention. None of these is measured. The live decode/book/signal chain executes on one thread, with no reported contention measurement. The paper's headline tail attribution therefore comes from a path where 87% to 99.7% of messages met an empty ring.

Bypassing the queue also changes ordering. Once fast_send acquires the lock, it executes ahead of anything waiting in the receiver's mailbox. Maciejewski says plainly that callers requiring strict FIFO must use send. Delivery mode is chosen by the sender, with the consequence appearing at the receiver.

The cyclic detector offers two policies. Its permissive policy keys on (actor, message-class) rather than the actor alone. This permits callback patterns and allows reentrancy with them, so a nested handler may observe and mutate actor state during an update. The paper assigns reentrancy safety in this mode to the programmer. The conservative policy prevents that behavior while rejecting some legitimate callbacks. The choice is real, and neither branch is measured.

We did not find a comparison with anything beyond the framework's own asynchronous path. There is no hand-written lock-free pipeline and no other actor runtime tested on the same box. The 37x and 110x ratios remain internal comparisons.

A set of multi-millisecond stalls is accepted as real and left unexplained, including a 5567 us maximum on NQ book and 1148 us on ES book. The live evidence comes from one machine during one 53-minute session, without cross-day or cross-venue replication. Mailbox-queue microbenchmarks on the pinned EPYC box face a separate issue: a single cross-thread message does not distinguish among the four queue implementations. Thread placement shifts the result by 2.2x, exceeding the spread between them. Absolute figures from that box carry little weight. The inter-row ratios carry the claim.

The actionable result is narrow. When a co-located path usually finds an empty ring, actor-style isolation costs about 10 ns per hop and packet structure owns the tail. A saturated run would change my view of everything beyond that. Show the fallback ratio and sweep chain depth. Then I would build on the claim that the framework makes no measurable contribution to the tail.