soothfast v0.4.3

soothfast-measure API reference#

Generated by cargo soothfast docs reference Measurements and verified claims come from the latest baseline; CI gates them.

soothfast_measure#

CountingAllocator struct#

rust · ignore
pub struct CountingAllocator

main function#

rust · ignore
pub fn main()

soothfast_measure::alloc#

AllocMeasurement struct#

rust · ignore
pub struct AllocMeasurement { pub allocs: u64, pub bytes: u64 }

Per-iteration allocation counts for one item.

measure function#

rust · ignore
pub fn measure(runner: impl Fn(&mut Bencher)) -> AllocMeasurement

Measure one workload iteration's allocations: warm once (lazy statics, allocator pools), then take the minimum over a few single-iteration runs.

soothfast_measure::asyncexec#

AsyncMeasurement struct#

rust · ignore
pub struct AsyncMeasurement { pub polls: u64, pub wakes: u64 }

Per-iteration async behavior for one item.

measure function#

rust · ignore
pub fn measure(runner: impl Fn(&mut Bencher)) -> AsyncMeasurement

Warm once, then min-of-3 single iterations (same shape as the alloc backend — counts, not times, so min is exact).

soothfast_measure::callgrind#

Guest struct#

rust · ignore
pub struct Guest { pub cpu: String, pub glibc: String, pub libc: String, pub valgrind: String }

What decides callgrind's Ir besides the binary: the CPU valgrind shows the guest (not the host's, which valgrind replaces with a synthesized one), the glibc the guest loads, and the valgrind counting it.

Measurement struct#

rust · ignore
pub struct Measurement { pub ir: u64, pub functions: Vec<(String, String)> }

One item's callgrind result: per-iteration Ir, and every function the longer run executed as sorted, deduplicated (object, mangled symbol).

annotate function#

rust · ignore
pub fn annotate(id: &str) -> Result<String, String>

Human triage report: top self-cost functions for one item's workload.

guest function#

rust · ignore
pub fn guest() -> Option<Guest>

Ask this binary, under valgrind as a measurement runs it, what it sees. None where the guest cannot say (not x86_64, not glibc).

measure function#

rust · ignore
pub fn measure(id: &str) -> Result<Measurement, String>

Per-iteration Ir for one item.

measure_all function#

rust · ignore
pub fn measure_all(ids: &[&str]) -> Vec<Result<Measurement, String>>

Per-iteration Ir for many items, measured concurrently (Ir counts are timing-independent). Results come back in input order.

rust · ignore
pub fn print_guest_view()

The guest half of [guest]: prints guest <cpuid hash> <glibc version> <loaded libc path>, or nothing where any is unknown. The path is hashed outside valgrind, where reading the file costs nothing.

probe function#

rust · ignore
pub fn probe() -> Result<(), String>

Can valgrind actually run THIS binary? valgrind --version is not enough: an AVX-512-compiled glibc loader SIGILLs before main().

soothfast_measure::perfcnt#

PerfMeasurement struct#

rust · ignore
pub struct PerfMeasurement { pub instructions: u64, pub cycles: u64, pub cache_refs: u64 }

Per-iteration counter values for one item.

measure function#

rust · ignore
pub fn measure(runner: impl Fn(&mut Bencher)) -> PerfMeasurement

Measure per-iteration instructions/cycles/cache-refs (min of 3 rounds).

measure_instructions function#

rust · ignore
pub fn measure_instructions(runner: impl Fn(&mut Bencher)) -> u64

Instructions-only measurement, for complexity sweeps.

probe function#

rust · ignore
pub fn probe() -> Result<(), String>

Can this environment open an instructions counter on itself?

soothfast_measure::stats#

Summary struct#

rust · ignore
pub struct Summary { pub median: f64, pub mad: f64, pub min: f64, pub max: f64 }

Robust summary of one sample set.

summarize function#

rust · ignore
pub fn summarize(values: &mut [f64]) -> Summary

Summarize a non-empty sample set. Sorts in place.

verified claims
✓allocallocs 4 <= 8
✓complexityclaimed O(n log n); growth drift x1.20 over sizes [1024, 4096, 16384] (limit x2.5)
measured as `soothfast_measure::bench_summarize`
median walltime (ns)551679
p99 walltime (ns)735046
allocations/iter4
allocated bytes/iter524288

soothfast_measure::sweep#

DRIFT_LIMIT constant#

rust · ignore
pub const DRIFT_LIMIT: f64 = 2.5

Growth beyond the claim must stay under this factor across the sweep. 2.5x tolerates n vs n log n ambiguity (~1.4x over a 16x size range) while catching n -> n^2 (16x) the day it happens.

SweepOutcome struct#

rust · ignore
pub struct SweepOutcome { pub drift: f64, pub ok: bool }

Verdict of one complexity sweep: how far measured growth strayed from the claimed class, and whether it stayed within [DRIFT_LIMIT].

class_value function#

rust · ignore
pub fn class_value(class: &str, n: f64) -> f64

Cost model for a claimed class at size n.

evaluate function#

rust · ignore
pub fn evaluate(class: &str, sizes: &[usize], values: &[f64]) -> SweepOutcome

Evaluate measured values (one per size, same order) against a claim.

verified claims
✓allocallocs 0 <= 0
measured as `soothfast_measure::bench_sweep_evaluate`
median walltime (ns)22
p99 walltime (ns)23
allocations/iter0
allocated bytes/iter0

soothfast_measure::walltime#

DEFAULT_SAMPLES constant#

rust · ignore
pub const DEFAULT_SAMPLES: u32 = 31

Default sample count; odd so the median is a real observation.

WallMeasurement struct#

rust · ignore
pub struct WallMeasurement { pub summary: Summary, pub p99_ns: f64, pub samples: u32, pub iters: u64 }

Wall-clock summary for one item, in ns per iteration.

calibrate function#

rust · ignore
pub fn calibrate(samples: u32) -> f64

A/A noise calibration: measure an identical reference workload against itself repeatedly; the worst relative disagreement between medians is the environment's observed noise floor (percent). Gates wider than this floor are meaningful; gates inside it are coin flips.

measure function#

rust · ignore
pub fn measure(runner: impl Fn(&mut Bencher), samples: u32) -> WallMeasurement

Measure one item: pilot run to pick iters, then samples timed loops.

built with cargo soothfast docs build source