Skip to content

feat(driver): eventfd-driven reaping to replace the 200us busy-poll (backlog#1102)#1

Merged
houseme merged 1 commit into
mainfrom
feat/eventfd-reaping
Jul 10, 2026
Merged

feat(driver): eventfd-driven reaping to replace the 200us busy-poll (backlog#1102)#1
houseme merged 1 commit into
mainfrom
feat/eventfd-reaping

Conversation

@houseme

@houseme houseme commented Jul 10, 2026

Copy link
Copy Markdown
Collaborator

What

First productionization step for rustfs/backlog#1102: replace the spike's 200µs busy-poll driver loop with eventfd-driven reaping.

Change

Two eventfds wake the driver loop:

  • one is registered with the ring (IORING_REGISTER_EVENTFD) so the kernel signals it on every CQE;
  • the other is signaled by submit()/shutdown so a new message wakes the loop immediately.

The loop blocks in poll() on both, with a 50ms heartbeat that only bounds the wait (so the bounded-drain deadline is still checked and a queued cancel is picked up promptly). All intake/submit/reap/bounded-drain logic is unchangedsubmit() still runs every turn, flushing the NODROP overflow list, so the rustfs/backlog#1056 hang does not return.

Internal only: the public API and every cancel-safety invariant are unchanged.

Verification

  • All 11 cancel-safety tests pass under real io_uring — both run-docker.sh legs (leg 1 seccomp-blocked → graceful degradation; leg 2 unconfined → real io_uring), release build.
  • cargo fmt --check + clippy --all-targets -D warnings clean.

Scope

The dedicated driver thread stays. Moving reaping onto a tokio AsyncFd (removing the thread, integrating with the tokio reactor) is the larger remaining part of #1102, along with O_DIRECT, async backpressure, and the singleton ring.

…rustfs/backlog#1102)

The spike drove the loop with a 200us sleep + 50ms recv_timeout busy-poll,
adding a latency floor and idle CPU. Replace it with two eventfds: one is
registered with the ring (IORING_REGISTER_EVENTFD) so the kernel signals it on
every CQE, the other is signaled by submit()/shutdown so a new message wakes
the loop immediately. The loop blocks in poll() on both (with a 50ms heartbeat
that only bounds the wait so the drain deadline is still checked and queued
cancels are picked up). All intake/submit/reap/bounded-drain logic is unchanged
— submit() still runs each turn, flushing the NODROP overflow list, so the
rustfs/backlog#1056 hang does not return.

This is internal only: the public API and every invariant are unchanged, and
all 11 cancel-safety tests pass under real io_uring (both run-docker.sh legs).
The dedicated driver thread stays; moving reaping onto a tokio AsyncFd (no
thread) is the larger remaining step.

Co-Authored-By: heihutu <heihutu@gmail.com>
@houseme houseme merged commit ea6b920 into main Jul 10, 2026
3 checks passed
@houseme houseme deleted the feat/eventfd-reaping branch July 10, 2026 03:05
houseme added a commit that referenced this pull request Jul 10, 2026
The README described eventfd reaping, O_DIRECT, and LocalIoBackend
integration as unlanded and listed streaming reads on the roadmap; all of
that has since merged or been closed by measurement. Bring it in line with
the actual public API and record the honest performance picture.

README changes:
- status now reflects that the read path is wired into rustfs/rustfs behind
  a runtime probe and off by default (RUSTFS_IO_URING_READ_ENABLE), and how
  to pin the git dependency;
- document sharded rings (probe_and_start_sharded) and native O_DIRECT
  (read_at_direct) with runnable examples matching the current signatures;
- a "when this crate helps — and when it does not" section reporting the
  measured results, including where io_uring loses (single sequential
  stream, low concurrency) and the roughly-neutral end-to-end S3 GET, plus
  the two benchmarking traps this repo hit (a 76x regression mistaken for a
  win, and page-cache-hit microbenchmarks not transferring end-to-end);
- roadmap trimmed to what is actually open (write path, register_files,
  SQPOLL) with the closed-by-measurement decisions moved to the CHANGELOG.

Add CHANGELOG.md (Keep a Changelog format): every landed change #1..#6 with
the commit that carried it, the pre-history of the audited spike, and a
"decisions recorded, not implemented" section so the NO-GO items are not
silently re-opened.

Verified README claims against source: the six documented signatures match
src/driver.rs, ProbeFailure/StatsSnapshot/UringDriver are the lib exports,
and the O_DIRECT example's alignment passes the driver's validation.

Co-authored-by: heihutu <heihutu@gmail.com>
houseme added a commit that referenced this pull request Jul 10, 2026
* docs: refresh README for shipped features and add a CHANGELOG

The README described eventfd reaping, O_DIRECT, and LocalIoBackend
integration as unlanded and listed streaming reads on the roadmap; all of
that has since merged or been closed by measurement. Bring it in line with
the actual public API and record the honest performance picture.

README changes:
- status now reflects that the read path is wired into rustfs/rustfs behind
  a runtime probe and off by default (RUSTFS_IO_URING_READ_ENABLE), and how
  to pin the git dependency;
- document sharded rings (probe_and_start_sharded) and native O_DIRECT
  (read_at_direct) with runnable examples matching the current signatures;
- a "when this crate helps — and when it does not" section reporting the
  measured results, including where io_uring loses (single sequential
  stream, low concurrency) and the roughly-neutral end-to-end S3 GET, plus
  the two benchmarking traps this repo hit (a 76x regression mistaken for a
  win, and page-cache-hit microbenchmarks not transferring end-to-end);
- roadmap trimmed to what is actually open (write path, register_files,
  SQPOLL) with the closed-by-measurement decisions moved to the CHANGELOG.

Add CHANGELOG.md (Keep a Changelog format): every landed change #1..#6 with
the commit that carried it, the pre-history of the audited spike, and a
"decisions recorded, not implemented" section so the NO-GO items are not
silently re-opened.

Verified README claims against source: the six documented signatures match
src/driver.rs, ProbeFailure/StatsSnapshot/UringDriver are the lib exports,
and the O_DIRECT example's alignment passes the driver's validation.

Co-Authored-By: heihutu <heihutu@gmail.com>

* fix: gate Linux-only benchmark examples

---------

Co-authored-by: heihutu <heihutu@gmail.com>
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