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.

01

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.

shell
cargo add numaperf
02

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.

main.rs
use numaperf::Topology;

let topo = Topology::discover()?;
let node0 = topo.numa_nodes()[0].id();
03

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.

main.rs
use numaperf::ScopedPin;

let _pin = ScopedPin::to_node(&topo, node0)?;
// this thread now runs on node0's CPUs until _pin drops
04

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.

main.rs
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
05

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.

main.rs
// 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.