Skip to content

docs(perf): record the SQPOLL send-ring A/B as a measured negative - #380

Closed
gg582 wants to merge 1 commit into
devfrom
docs/sqpoll-send-negative
Closed

gg582 wants to merge 1 commit into
devfrom
docs/sqpoll-send-negative

Conversation

@gg582

@gg582 gg582 commented Oct 16, 2026

Copy link
Copy Markdown
Member

Summary

  • Records the completed A/B for the audit's Add doxygen style comments #1 ranked opportunity — zero-syscall response write via the SQPOLL send ring — as a measured negative, following the doc's existing convention for the reverted multishot-accept (1.1) and listen-NODELAY (1.3) experiments.
  • Without this, the doc's ranked list keeps telling the next reader (human or agent) to chase the biggest "headroom" first.

What was measured (3 interleaved rounds per leg, cwist_bench, base-vs-base noise RPS ±2–4% / P99 ±8% / P99.999 ±25%)

The mechanism worked exactly as designed — strace shows sendmsg dropping from 1.00 → 0.00 per request — but:

leg RPS P99.999
c256 base → candidate 352k → 178k (−49.5%) 46.5 → 77.0 ms
c400 base → candidate 386k → 195k (−49.5%) 56.7 → 77.6 ms

Structural cause, same shape as the reverted multishot accept: the synchronous path re-arms the connection for reads immediately after sendmsg returns; the async path pays a full extra reactor round-trip per request (SEND CQE → ring-fd poll wake → reap → re-arm → next read wake) plus ~65% more io_uring_enter calls. Not merged, no knob shipped; code discarded per the meaningful-change-only rule.

The branch-implementation notes (per-worker ring after fork, CQ reader via reactor-registered ring fd, obuf lifetime gated on CQE, -EPIPE semantics, the IORING_SQ_NEED_WAKEUP idle-stall gotcha) are summarized in the doc entry for whoever considers the pipelining-across-the-gap architecture that might actually win.

Test plan

  • Doc-only change; no code touched

The audit's #1 ranked opportunity (zero-syscall response write via the
probed-only cwist_io_uring_sqpoll_send ring) was implemented on a branch
and A/B-measured: the mechanism worked exactly (strace: sendmsg 1.00 ->
0.00 per request) but throughput halved and the tail worsened on both
legs (c256 352k -> 178k RPS, P99.999 46.5 -> 77.0 ms; c400 386k -> 195k,
56.7 -> 77.6 ms; noise band RPS +-2-4%). Structural cause, same shape as
the reverted multishot accept: the async path pays a full extra reactor
round-trip per request (SEND CQE -> ring-fd wake -> reap -> re-arm) and
~65% more io_uring_enter calls. Not merged, no knob shipped.

Mark ranked item 1 NEGATIVE with the numbers and the no-retry caveat so
the headroom is not chased again blind; adjust item 3's reference to it.
@gg582 gg582 closed this Oct 16, 2026
@gg582 gg582 reopened this Oct 16, 2026
@gg582 gg582 closed this Oct 16, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant