win-numa-sys
Memory-safe Rust over the Windows NUMA APIs.
Windows provides some NUMA concepts; this crate builds library notions on top of them. Whether a client uses them is up to the client.
What is here
NumaNode-- a node number, as Windows numbers them. A newtype because a node number and a count of nodes are both small integers and are trivially swapped at a call site.NumaBuffer-- an owned allocation made withVirtualAllocExNumaand released withVirtualFree, so a buffer can be placed on a chosen node rather than wherever the default allocator lands it.highest_numa_node()andvolume_numa_node(handle)-- the two questions Windows will answer about nodes, wrapped so a caller can find a node to pass without writing the FFI.
What is not here, and will not be
Any opinion about which node anything should use. This crate reports what Windows says and allocates where it is told. It does not map a file to a node, does not shard anything, and does not choose a node on a caller's behalf.
The -sys suffix is that promise. In this workspace the suffix means thin over Win32, memory-safe,
adding no policy -- see the repository's
DESIGN-NOTES.md,
where a sibling crate drops the suffix for failing exactly that test.
The name
The first crate here to take win- rather than windows-. windows is Microsoft's namespace, and
a crate published as windows-numa-sys today is a name they may reasonably want tomorrow; see
DESIGN-NOTES.md. Existing crates keep their
names for now.
A node argument is a preference, not an instruction
VirtualAllocExNuma's parameter is nndPreferred, and the name is the contract. A successful
allocation is not evidence that the pages landed on the node that was asked for. Two things
follow, both of which have already caught someone in this workspace:
- Committed pages are demand-zero, so until something writes to them no physical page has been drawn from the preferred node at all. Measuring placement means faulting the pages in first.
- An invalid node is refused -- but
u32::MAXis not a test of that, because it is the API's own no-preference sentinel and is accepted by design. A measurement that asks foru32::MAXand sees it succeed has measured the sentinel, not a range check.
Observing where pages actually landed needs QueryWorkingSetEx, which lives in
windows-placement-probe today; whether it moves here is CHECKLIST.md N-1.2.
Buffer traits live with whoever owns them
NumaBuffer implements no I/O buffer trait, because this crate defines none. windows-ioring-sys
and windows-overlapped-io-sys each already have their own IoBuf/IoBufMut pair, and a third
copy here would have made that duplication harder to resolve rather than easier.
A consumer that owns such a trait implements it for NumaBuffer -- the orphan rule permits exactly
that, since the trait is theirs -- over the inherent as_ptr, as_mut_ptr and len.
windows-ioring-sys does so, and keeps re-exporting NumaBuffer so windows_ioring_sys::NumaBuffer
still resolves.