feat(fast_io): IOCP completion-port pump for batched writes (#1897)#3531
Merged
Conversation
Add CompletionPump: a shared completion-port driver that owns a worker thread looping on GetQueuedCompletionStatusEx and dispatches each completion entry to a per-operation handler keyed by the OVERLAPPED pointer. This is the Windows analogue of an io_uring CQE drain and is the foundational building block for the upcoming batched-write API (#1898), the concurrent file/socket paths (#1928-#1932), and the IOCP benchmark harness (#1899). Existing IocpReader/IocpWriter create a private port and inline-call GetQueuedCompletionStatus per operation, so the pump introduces a process-wide proactor without disturbing those single-op paths. Cross-platform: real implementation lives behind #[cfg(all(target_os = "windows", feature = "iocp"))]; non-Windows targets get an Unsupported-returning stub so the crate still compiles on Linux and macOS. All unsafe stays inside fast_io per the workspace unsafe-code policy.
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.
Closes #1897.
Summary
CompletionPumpincrates/fast_io/src/iocp/pump.rs: a sharedcompletion-port driver that spawns a worker thread looping on
GetQueuedCompletionStatusExand dispatches each entry to a per-opCompletionHandlerkeyed by the address of itsOVERLAPPED. Thisis the Windows analogue of an io_uring CQE drain.
crates/fast_io/src/iocp/mod.rsandre-export
CompletionHandler,CompletionPump,IocpPumpConfig,oneshot_handler, and (Windows-only)iocp_post_completionfromcrates/fast_io/src/lib.rs.crates/fast_io/src/iocp_stub.rswithUnsupported-returning stubs so the crate still compiles on Linuxand macOS.
PostQueuedCompletionStatuswith a sentinelcompletion key;
Dropruns the same path so abandoned pumps stillreap their worker thread.
OVERLAPPED.Internal,translated to Win32 DOS errors for the most common overlapped-I/O
outcomes (
STATUS_END_OF_FILE,STATUS_CANCELLED,STATUS_INSUFFICIENT_RESOURCES,STATUS_IO_TIMEOUT); anythingunrecognised passes through
io::Error::from_raw_os_error.fast_ioper the workspace unsafe-codepolicy. No new unsafe in
transfer,core,cli, orengine.Why this PR is foundational
#1898 (batched-write API matching the
IoUringDiskBatchsurface),#1929/#1930/#1928 (concurrent IOCP paths in the receiver / disk-commit /
delta-apply hot paths), #1931/#1932 (stress tests under load), #1900
(CI matrix expansion), and #1899 (benchmark harness) all depend on
having a proactor in place. Today every
IocpReader::read_atandIocpWriter::write_atallocates a private port and inline-callsGetQueuedCompletionStatus; the audit atdocs/audits/windows-iocp-benchmark.md(sections 1.1, 1.2, 5.1)documents the gap. Subsequent PRs will layer batched submission on
top of this pump.
Audit findings (pre-implementation)
crates/fast_io/src/iocp/completion_port.rs:17-86- existingCompletionPortis a simple RAII wrapper, onlyassociate(handle, key)and
handle(). No drain function.crates/fast_io/src/iocp/file_reader.rs:131-149andcrates/fast_io/src/iocp/file_writer.rs:140-156- both inline-callGetQueuedCompletionStatusper op, blocking the calling thread.docs/audits/windows-iocp-benchmark.md:136-141- "eachIocpReader/IocpWriterallocates its ownCompletionPort... no shared port,no thread-pool drainer, no per-process proactor."
PRs found: feat: add Windows IOCP async file I/O in fast_io crate #3299 (scaffold), docs(fast_io): propose Windows IOCP benchmark plan (#1899) #3510 (benchmark plan Fix RPM artifact paths and cargo xtask alias #1899). No pump.
What is left for downstream PRs
IocpDiskBatchon top of thepump, mirroring
IoUringDiskBatch(crates/fast_io/src/io_uring/disk_batch.rs).the receiver basis-read path, the disk-commit thread, and the
delta-apply hot path. Replace per-op
GetQueuedCompletionStatuscalls in
IocpReader::read_at/IocpWriter::write_atwith pumpregistration.
cancellation under load.
Test plan
cargo fmt --all -- --checkcleancargo clippy -p fast_io --all-targets --all-features --no-deps -- -D warningscleancargo clippy --workspace --all-targets --all-features --no-deps -- -D warningscleancargo nextest run -p fast_io --all-features -E 'test(iocp)'(23 tests pass on macOS stub path including 3 new pump-stub tests)pump_dispatches_overlapped_write_completion(writes viaWriteFileagainstFILE_FLAG_OVERLAPPEDhandle, asserts the pump's worker fires the registered handler with the correct byte count)pump_post_completion_round_trip(manualPostQueuedCompletionStatuswith synthetic OVERLAPPED, asserts dispatch)