perf(net): receive-path fixes, no-alloc enforcement over the whole frame, latency roadmap - #2
Merged
Merged
Conversation
Four-track research pass: repo hot-path inventory, venue wire formats, software tick-to-trade practice, tail-latency engineering. Records the three-way split of the gap (environment tail, JSON ceiling, compute already competitive) and the phase order for closing it.
…me reader The probe covered the book — 0.3% of the frame. The claim it existed to enforce is about the other 99.7%: the decoder, Feed::handle end to end with the checksum verified, and the transport's poll loop. All three are allocation-free in steady state; now CI says so instead of the README. No Catch2 macros run inside the armed regions — an assertion handler may allocate, and each guarded loop's work is asserted after disarming (levels seen, checksums verified, messages pumped).
…caller Two receive paths grew a std::vector<char> by a 32 KiB chunk on every socket read and trimmed it back to what arrived; vector::resize value-initializes, so that was 32 KiB of memset per read over bytes the transport was about to overwrite. net::ByteBuffer is the same vector with an allocator whose construct() default-initializes — resize becomes bookkeeping, everything else is unchanged. The Schannel decrypt path also copied plaintext twice (DecryptMessage's in-place output into plain_, plain_ into the caller) and built a fresh vector for the unconsumed tail of every pipelined TLS record — a heap allocation on the common path, since a busy feed routinely lands the next record behind the current one in the same segment. Plaintext now goes straight to the caller's buffer, overflow beyond the caller's ask is the only thing plain_ holds, and the tail is moved in place by take_extra, which already existed and already did exactly this. Verified live: 8 s Kraken capture through the new path, then replayed — 250 of 250 checksums match, so the decrypted bytes are byte-exact.
Opt-in -march=native (/arch:AVX2 on MSVC) plus LTO, for measuring the ceiling on one's own hardware. Off by default and not inherited by any other preset: the README's numbers must come from the configuration a consumer gets, and a binary tuned to the build machine dies with an illegal instruction on the next one.
GCC's -Wsign-conversion under -Werror rejects promoting the int from the conditional into a uint64_t accumulator; MSVC and Clang did not flag it, which is what the GCC floor job exists to catch.
set_read_timeout(0) now means busy-poll — non-blocking socket, reads return kTimeout immediately — rather than the platforms' block-forever. crossbook_capture grows --busy-poll and, where the platform can say, a kernel-to-user delivery histogram: the gap between the kernel stamping a segment and the loop holding the decoded message, which is the number busy-poll exists to shrink. The timestamps were a lesson in what Linux actually offers TCP: SIOCGSTAMP is unsupported for SOCK_STREAM and SO_TIMESTAMPNS is silently a no-op there — both learned empirically. The one API that works is SO_TIMESTAMPING with RX_SOFTWARE, delivered as SCM_TIMESTAMPING control messages on the recvmsg that carries the data. Which forces an architectural correction: OpenSSL can no longer own the fd, because a backend that lets SSL_read call recv() itself can never see a control message. Reads now flow through TcpSocket via a custom BIO on the OpenSSL path — the same route Schannel always took — with kTimeout mapped to the retry flags SSL_read expects. The transport also gains its first tests: loopback coverage of the busy-poll contract, the ordinary timed path, and the timestamp, wired in via a deferred CMake hook because tests/ is configured before src/net exists. Verified live on Linux against Kraken over TLS: busy-poll cut kernel-to-user p50 from 150.4 us to 82.4 us in back-to-back 15 s captures (WSL2, unpinned; the p99 wants the isolated core the roadmap pairs it with). Windows: 344/344 tests, live capture clean, timestamps honestly reported unavailable.
…ointed at Hand-rolled reader for schema spot_stream 1:0 — depth diff and depth snapshot to the same DecodedMessage the JSON decoders produce, same route-before-trust and refuse-rather-than-round contracts, and SBE blockLengths honoured so a newer minor schema skips cleanly instead of desyncing. Ten fixture tests hand-encoded from the schema XML, including a byte-by-byte truncation sweep and a feed-level end-to-end over the recovery state machine. Live capture is blocked on an Ed25519 API key, which stream-sbe.binance.com requires even for public data. Also: roadmap updated with what the phases measured — the WSL2 sweep (6.3x tail improvement from the OS change alone), the busy-poll live numbers, and one lever measured dead (unchecked digit accumulation in parse_fixed: same-state A/B showed noise; reverted, recorded, so nobody re-optimizes it on vibes). 354/354 tests Windows, 353/353 Linux.
…s its wrap The loopback test qualified htonl/ntohs with :: — a parse error on macOS, where both are macros. And the SBE files now carry the exact formatting clang-format wanted for the lines it flagged. Caught by the matrix, as designed: MSVC, GCC 13, and clang 14 all accepted both.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Phase 0 of LATENCY-ROADMAP.md, which this PR also adds.
What
Verification
Note: main's CI is currently red on the fuzz smoke and format jobs from an unrelated commit; a fix is already in flight on main. This branch is off 909ae9e and touches neither area.
🤖 Generated with Claude Code