Quickstart
From cargo add to guaranteed locality.
Five steps, all in safe Rust. The snippets are adapted from the project README — nothing here fabricates a benchmark. The full reference lives in the docs.
Add the crate
numaperf is published on crates.io. Add it with cargo. MSRV is 1.70; Linux x86_64 and aarch64 are fully supported, macOS degrades gracefully.
cargo add numaperf Discover the topology
Read the real machine at runtime — NUMA nodes, their CPUs, and inter-node distances — instead of hard-coding a layout that differs across hardware.
use numaperf::Topology;
let topo = Topology::discover()?;
let node0 = topo.numa_nodes()[0].id(); Pin the thread
ScopedPin pins the current thread to a node’s CPUs and restores the previous affinity when the guard drops. No affinity leaks across scopes.
use numaperf::ScopedPin;
let _pin = ScopedPin::to_node(&topo, node0)?;
// this thread now runs on node0's CPUs until _pin drops Place memory with a policy you chose
Allocate a region with an explicit MemPolicy and Prefault::Touch so the pages are faulted in and placed at allocation time — local to node0, not wherever first-touch lands.
use numaperf::{NumaRegion, MemPolicy, NodeMask, Prefault};
let region = NumaRegion::anon(
1024 * 1024 * 1024,
MemPolicy::Bind(NodeMask::single(node0)),
Default::default(),
Prefault::Touch,
)?;
// region is now guaranteed local to node0 Observe locality
Once memory and threads are placed, use the observability crate to track locality ratios and cross-node traffic — so a regression shows up as a number, not a wandering p99.
// numaperf-perf reports locality ratios and cross-node
// traffic you can put on a dashboard, not just in a latency test. That’s the loop
Browse the full feature set, read how it works, or see who uses it.