benches: add SMARM_BENCH_SETS (default 5) for stable medians
Each run_n call now collects ITERS × SETS raw samples across all sets (one warmup before the first set, discarded), then takes a single global median. Previously only ITERS=15 samples were taken per bench invocation, which produced noisy results in sweep.py regress. SMARM_BENCH_SETS is read from the environment; the default of 5 gives 75 samples per bench row (5×15), matching the stability of the multi-run bash approach without requiring multiple cargo bench invocations. Also moves scripts/bench_rq.sh into benches/ alongside sweep.py. The cd "$(dirname "$0")/.." path logic is unchanged.
This commit is contained in:
+18
-7
@@ -29,6 +29,13 @@ fn available_threads() -> usize {
|
|||||||
std::thread::available_parallelism().map(|n| n.get()).unwrap_or(1)
|
std::thread::available_parallelism().map(|n| n.get()).unwrap_or(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn env_sets() -> u32 {
|
||||||
|
std::env::var("SMARM_BENCH_SETS")
|
||||||
|
.ok()
|
||||||
|
.and_then(|v| v.parse().ok())
|
||||||
|
.unwrap_or(5)
|
||||||
|
}
|
||||||
|
|
||||||
fn print_header(title: &str) {
|
fn print_header(title: &str) {
|
||||||
println!("\n{}", "=".repeat(80));
|
println!("\n{}", "=".repeat(80));
|
||||||
println!(" {title}");
|
println!(" {title}");
|
||||||
@@ -41,14 +48,17 @@ fn print_header(title: &str) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn run_n<F: FnMut() -> (u64, u128)>(name: &str, n: u32, mut f: F) {
|
fn run_n<F: FnMut() -> (u64, u128)>(name: &str, n: u32, mut f: F) {
|
||||||
let mut times = Vec::new();
|
let sets = env_sets();
|
||||||
|
let mut times = Vec::with_capacity((n * sets) as usize);
|
||||||
let mut last = 0u64;
|
let mut last = 0u64;
|
||||||
// One warmup iteration, discarded.
|
// One warmup before all sets, discarded.
|
||||||
let _ = f();
|
let _ = f();
|
||||||
for _ in 0..n {
|
for _ in 0..sets {
|
||||||
let (v, t) = f();
|
for _ in 0..n {
|
||||||
times.push(t);
|
let (v, t) = f();
|
||||||
last = v;
|
times.push(t);
|
||||||
|
last = v;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
times.sort_unstable();
|
times.sort_unstable();
|
||||||
let median = times[times.len() / 2];
|
let median = times[times.len() / 2];
|
||||||
@@ -406,7 +416,8 @@ fn main() {
|
|||||||
let n = available_threads();
|
let n = available_threads();
|
||||||
println!("smarm general benchmarks");
|
println!("smarm general benchmarks");
|
||||||
println!("available parallelism: {n} threads");
|
println!("available parallelism: {n} threads");
|
||||||
println!("ITERS={ITERS} (+1 warmup, discarded)");
|
let sets = env_sets();
|
||||||
|
println!("ITERS={ITERS}×{sets} sets = {} samples (+1 warmup, discarded)", ITERS * sets);
|
||||||
println!(
|
println!(
|
||||||
"CHAIN_DEPTH={CHAIN_DEPTH}, YIELD_TASKS={YIELD_TASKS}×{YIELD_ROUNDS}, \
|
"CHAIN_DEPTH={CHAIN_DEPTH}, YIELD_TASKS={YIELD_TASKS}×{YIELD_ROUNDS}, \
|
||||||
PRIME_N={PRIME_N}/{PRIME_WORKERS} workers, PP_ROUNDS={PP_ROUNDS}"
|
PRIME_N={PRIME_N}/{PRIME_WORKERS} workers, PP_ROUNDS={PP_ROUNDS}"
|
||||||
|
|||||||
@@ -40,6 +40,13 @@ fn available_threads() -> usize {
|
|||||||
std::thread::available_parallelism().map(|n| n.get()).unwrap_or(1)
|
std::thread::available_parallelism().map(|n| n.get()).unwrap_or(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn env_sets() -> u32 {
|
||||||
|
std::env::var("SMARM_BENCH_SETS")
|
||||||
|
.ok()
|
||||||
|
.and_then(|v| v.parse().ok())
|
||||||
|
.unwrap_or(5)
|
||||||
|
}
|
||||||
|
|
||||||
fn print_header(title: &str) {
|
fn print_header(title: &str) {
|
||||||
println!("\n{}", "=".repeat(80));
|
println!("\n{}", "=".repeat(80));
|
||||||
println!(" {title}");
|
println!(" {title}");
|
||||||
@@ -52,13 +59,17 @@ fn print_header(title: &str) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn run_n<F: FnMut() -> (u64, u128)>(name: &str, n: u32, mut f: F) {
|
fn run_n<F: FnMut() -> (u64, u128)>(name: &str, n: u32, mut f: F) {
|
||||||
let mut times = Vec::new();
|
let sets = env_sets();
|
||||||
|
let mut times = Vec::with_capacity((n * sets) as usize);
|
||||||
let mut last = 0u64;
|
let mut last = 0u64;
|
||||||
let _ = f(); // warmup
|
// One warmup before all sets, discarded.
|
||||||
for _ in 0..n {
|
let _ = f();
|
||||||
let (v, t) = f();
|
for _ in 0..sets {
|
||||||
times.push(t);
|
for _ in 0..n {
|
||||||
last = v;
|
let (v, t) = f();
|
||||||
|
times.push(t);
|
||||||
|
last = v;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
times.sort_unstable();
|
times.sort_unstable();
|
||||||
let median = times[times.len() / 2];
|
let median = times[times.len() / 2];
|
||||||
@@ -385,7 +396,8 @@ fn main() {
|
|||||||
let n = available_threads();
|
let n = available_threads();
|
||||||
println!("smarm smarm-favored benchmarks");
|
println!("smarm smarm-favored benchmarks");
|
||||||
println!("available parallelism: {n} threads");
|
println!("available parallelism: {n} threads");
|
||||||
println!("ITERS={ITERS} (+1 warmup, discarded)");
|
let sets = env_sets();
|
||||||
|
println!("ITERS={ITERS}×{sets} sets = {} samples (+1 warmup, discarded)", ITERS * sets);
|
||||||
println!(
|
println!(
|
||||||
"RECURSE_DEPTH={RECURSE_DEPTH}, HOT_YIELDS={HOT_YIELDS}×2, \
|
"RECURSE_DEPTH={RECURSE_DEPTH}, HOT_YIELDS={HOT_YIELDS}×2, \
|
||||||
UNCONT_MSGS={UNCONT_MSGS}, PANIC_TASKS={PANIC_TASKS}"
|
UNCONT_MSGS={UNCONT_MSGS}, PANIC_TASKS={PANIC_TASKS}"
|
||||||
|
|||||||
@@ -39,6 +39,13 @@ fn available_threads() -> usize {
|
|||||||
std::thread::available_parallelism().map(|n| n.get()).unwrap_or(1)
|
std::thread::available_parallelism().map(|n| n.get()).unwrap_or(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn env_sets() -> u32 {
|
||||||
|
std::env::var("SMARM_BENCH_SETS")
|
||||||
|
.ok()
|
||||||
|
.and_then(|v| v.parse().ok())
|
||||||
|
.unwrap_or(5)
|
||||||
|
}
|
||||||
|
|
||||||
fn print_header(title: &str) {
|
fn print_header(title: &str) {
|
||||||
println!("\n{}", "=".repeat(80));
|
println!("\n{}", "=".repeat(80));
|
||||||
println!(" {title}");
|
println!(" {title}");
|
||||||
@@ -51,13 +58,17 @@ fn print_header(title: &str) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn run_n<F: FnMut() -> (u64, u128)>(name: &str, n: u32, mut f: F) {
|
fn run_n<F: FnMut() -> (u64, u128)>(name: &str, n: u32, mut f: F) {
|
||||||
let mut times = Vec::new();
|
let sets = env_sets();
|
||||||
|
let mut times = Vec::with_capacity((n * sets) as usize);
|
||||||
let mut last = 0u64;
|
let mut last = 0u64;
|
||||||
let _ = f(); // warmup
|
// One warmup before all sets, discarded.
|
||||||
for _ in 0..n {
|
let _ = f();
|
||||||
let (v, t) = f();
|
for _ in 0..sets {
|
||||||
times.push(t);
|
for _ in 0..n {
|
||||||
last = v;
|
let (v, t) = f();
|
||||||
|
times.push(t);
|
||||||
|
last = v;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
times.sort_unstable();
|
times.sort_unstable();
|
||||||
let median = times[times.len() / 2];
|
let median = times[times.len() / 2];
|
||||||
@@ -434,7 +445,8 @@ fn main() {
|
|||||||
let n = available_threads();
|
let n = available_threads();
|
||||||
println!("smarm tokio-favored benchmarks");
|
println!("smarm tokio-favored benchmarks");
|
||||||
println!("available parallelism: {n} threads");
|
println!("available parallelism: {n} threads");
|
||||||
println!("ITERS={ITERS} (+1 warmup, discarded)");
|
let sets = env_sets();
|
||||||
|
println!("ITERS={ITERS}×{sets} sets = {} samples (+1 warmup, discarded)", ITERS * sets);
|
||||||
println!(
|
println!(
|
||||||
"STORM_BACKGROUND={STORM_BACKGROUND}, STORM_SPAWN={STORM_SPAWN}, \
|
"STORM_BACKGROUND={STORM_BACKGROUND}, STORM_SPAWN={STORM_SPAWN}, \
|
||||||
MPSC={MPSC_PRODUCERS}×{MPSC_PER_PRODUCER}, \
|
MPSC={MPSC_PRODUCERS}×{MPSC_PER_PRODUCER}, \
|
||||||
|
|||||||
Reference in New Issue
Block a user