throughput: batched UDP I/O (sendmmsg/recvmmsg) on the poll hot path #54
No reviewers
Labels
No labels
bug
documentation
duplicate
enhancement
good first issue
help wanted
invalid
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
femboy/yip!54
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/throughput-batched-io"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What
Batches the UDP send/recv on the default poll data-plane loop with
sendmmsg(2)/recvmmsg(2), collapsing per-packet syscalls into per-burst ones. Lever 3 of 3 for single-core 10-Gbit (cheap FEC ✓ #51 → fast AEAD ✓ #52 → batched I/O).Why
With FEC (~0.32 µs) and AEAD (~0.63 µs) cheap after #51/#52, per-packet UDP syscalls are the dominant single-core cost — the tx path issued ~2–3
sendtos per packet (one per FEC symbol) plus onerecvfromper datagram on rx.yip-ioalready hadsendmmsg/recvmmsgmechanics but they were unwired and lacked per-datagram addresses.How
crates/yip-io/src/poll.rs— two new addressed batch syscalls (co-located with the existing epoll code):send_mmsg(udp_fd, &[EgressDatagram])(onesendmmsg, each datagram to its owndstviamsg_name) andrecv_mmsg(udp_fd, bufs, lens, srcs)(one non-blockingrecvmmsg, capturing eachsrc).drain_udpdrains the rx burst withrecvmmsg;drain_tunaccumulates a TUN burst's egress symbols into onesend_mmsgviaflush_tx(chunked at 64);tickegress batched too.run_pollowns reusable batch buffers (rx bufsBoxed, 128 KiB). The now-dead per-packetsend_to_udpwas removed.run_poll's public signature is unchanged, soyipdneeds no edits.Opportunistic and latency-neutral — it batches only what epoll already has queued; a single ready packet still does one recv + one send syscall. No GSO — each datagram stays its own independent UDP packet, so two symbols of one FEC object are never lost as a unit (FEC loss-independence preserved).
Results
run-netns-tunnel,run-netns-tunnel-loss(10/10 under 10% netem loss — FEC still recovers with batched sends), andrun-arq-integrity(118 retransmits) all PASS. Fullcargo test --workspace: 0 failures;yip-io30/30 (addressedsend_mmsg/recv_mmsgunit-tested on loopback sockets).sendto/packet → onesendmmsg/burst; rx onerecvfrom/datagram → onerecvmmsg/burst.Final whole-branch review (opus): READY WITH FOLLOW-UPS — the
mmsgunsafe is memory-safe (copy-into-array-before-taking-pointer, no aliasing/OOB, SAFETY comments accurate), loop termination can't hang/spin, egress is behaviorally equivalent (no dropped path,tx_batchno leak), andyipdstays#.Follow-ups (non-blocking)
crates/yip-bench/tests/run-iperf-compare.shwedges in this environment (twoyipdcome up but iperf never completes — a harness/env flake, not a data-plane regression, since every other netns test passes traffic). The measured before/after Gbit figure — the spec's headline metric — is a tracked follow-up (fix/replace that harness).uring.rs(:857, :1040) still name the deletedsend_to_udp.recv_mmsgmaps an unparseable src to0.0.0.0:0silently; no explicit 64-cap unit test;flush_txdoc wording.Design docs
docs/superpowers/specs/2026-07-11-throughput-batched-io-design.mddocs/superpowers/plans/2026-07-11-throughput-batched-io.md🤖 Generated with Claude Code
https://claude.ai/code/session_01RVP6NnbDMAg1iTsMMTfL86