178de497f247cec37a485d3ea98d7b206bf65175 / alderbench/src/presets.rs · 6828 bytes · raw
//! Sweep presets — named workload sets + sweep params for the TUI's
//! picker screen + the `--preset` CLI arg. Each builder returns a
//! `Config` ready to hand to `Run::new`.
//!
//! Three presets:
//! - `stability` — stress-ng-cpu → y-cruncher-sse → y-cruncher-avx2,
//! 5 min (300s) each, all cores, 15s cooldown, looped to fill ~1 hour
//! (4 loops ≈ 49 min, 5 loops ≈ 61 min — we pick 5 to hit the target).
//! - `stability_core_cycle` — the same three workloads, but run on ONE
//! logical core at a time (cycling through all 16 twice), shorter
//! per-core duration (default 60s). Used to test peak single-core
//! clocks on chips with per-core load-based multipliers.
//! - `bench` — 7zip-bench → y-cruncher-sse → y-cruncher-avx2, 60s each,
//! all cores, 15s cooldown, single pass (the scores are the point;
//! looping doesn't improve the measurement).
use crate::config::{Config, WorkloadSpec};
/// Workload names available (the from_spec match arms in workload.rs).
/// The custom editor iterates this list for its toggle rows.
pub const AVAILABLE_WORKLOADS: &[&str] = &[
"stress-ng-cpu",
"y-cruncher-sse",
"y-cruncher-avx2",
"7zip-bench",
"c2c-latency",
"dram-latency",
];
/// Cores range options for the custom editor's per-workload cores field.
/// P = performance cores only, E = efficiency cores only, All = both.
/// Enter on the Cores field cycles through this list (wired in ui.rs).
pub const CORES_OPTIONS: &[&str] = &["0-15", "0-11", "12-15"];
fn spec(name: &str, duration_secs: u64, cores: &str) -> WorkloadSpec {
WorkloadSpec {
name: name.to_string(),
duration_secs,
cores: cores.to_string(),
}
}
/// Stability preset: cycle the three ISA-rail stress tests, 5 min each,
/// all cores, 15s cooldown, looped to fill ~1 hour. 4 loops = 49 min,
/// 5 loops = 61 min — pick 5 to cross the hour. Cancelable mid-run
/// (q in the TUI) so the user isn't committed to the full hour.
pub fn stability() -> Config {
Config {
workloads: vec![
spec("stress-ng-cpu", 300, "0-15"),
spec("y-cruncher-sse", 300, "0-15"),
spec("y-cruncher-avx2", 300, "0-15"),
],
cool_secs: 15,
loop_count: 5,
..Config::default()
}
}
/// Stability core-cycle preset: the same three workloads, but run on
/// ONE logical core at a time. Cycles through all 16 logical cores
/// twice. The `per_core_secs` arg sets the per-workload-per-core run
/// length (default 60s). Total run time ≈ 16 cores × 2 passes × 3
/// workloads × per_core_secs + cooldowns. Long, but cancelable.
///
/// This tests peak single-core clocks on chips with per-core load-based
/// multipliers — the question is whether each individual core is stable
/// at its own peak clock, not just whether the package is stable at the
/// all-core clock.
pub fn stability_core_cycle(per_core_secs: u64) -> Config {
let mut workloads: Vec<WorkloadSpec> = Vec::new();
// Two full passes across all 16 logical cores (0-15).
for pass in 0..2u32 {
for cpu in 0..16u32 {
// Three ISA rails, each on this single core.
for name in ["stress-ng-cpu", "y-cruncher-sse", "y-cruncher-avx2"] {
workloads.push(spec(name, per_core_secs, &cpu.to_string()));
}
}
let _ = pass; // pass count is the loop bound, not a body var
}
Config {
workloads,
cool_secs: 5, // shorter cooldown — single-core load doesn't heat the package
loop_count: 1, // the core-cycle IS the loop; don't loop the whole thing
..Config::default()
}
}
/// Bench preset: the three score-producing workloads, 60s each, all
/// cores, 15s cooldown, single pass. The scores (7z rating MIPS,
/// y-cruncher FFTv4 Gb/s) are the comparative-perf signal across OC
/// configs.
pub fn bench() -> Config {
Config {
workloads: vec![
spec("7zip-bench", 60, "0-15"),
spec("y-cruncher-sse", 60, "0-15"),
spec("y-cruncher-avx2", 60, "0-15"),
],
cool_secs: 15,
loop_count: 1,
..Config::default()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn stability_has_three_rails_five_loops() {
let cfg = stability();
assert_eq!(cfg.workloads.len(), 3);
assert_eq!(cfg.workloads[0].name, "stress-ng-cpu");
assert_eq!(cfg.workloads[1].name, "y-cruncher-sse");
assert_eq!(cfg.workloads[2].name, "y-cruncher-avx2");
assert_eq!(cfg.workloads[0].duration_secs, 300);
assert_eq!(cfg.cool_secs, 15);
assert_eq!(cfg.loop_count, 5);
}
#[test]
fn stability_core_cycle_visits_each_core_twice() {
let cfg = stability_core_cycle(60);
// 16 cores × 2 passes × 3 workloads = 96 entries.
assert_eq!(cfg.workloads.len(), 96);
// First three are cpu0 (stress-ng, sse, avx2).
assert_eq!(cfg.workloads[0].name, "stress-ng-cpu");
assert_eq!(cfg.workloads[0].cores, "0");
assert_eq!(cfg.workloads[1].name, "y-cruncher-sse");
assert_eq!(cfg.workloads[1].cores, "0");
assert_eq!(cfg.workloads[2].name, "y-cruncher-avx2");
assert_eq!(cfg.workloads[2].cores, "0");
// Last three are cpu15 on the second pass.
let last = &cfg.workloads[95];
assert_eq!(last.name, "y-cruncher-avx2");
assert_eq!(last.cores, "15");
// All single-core (no "0-15" range anywhere).
assert!(cfg.workloads.iter().all(|w| w.cores != "0-15"));
assert_eq!(cfg.loop_count, 1);
}
#[test]
fn stability_core_cycle_custom_duration() {
let cfg = stability_core_cycle(30);
assert_eq!(cfg.workloads[0].duration_secs, 30);
}
#[test]
fn bench_has_three_scored_workloads_single_pass() {
let cfg = bench();
assert_eq!(cfg.workloads.len(), 3);
assert_eq!(cfg.workloads[0].name, "7zip-bench");
assert_eq!(cfg.workloads[1].name, "y-cruncher-sse");
assert_eq!(cfg.workloads[2].name, "y-cruncher-avx2");
assert_eq!(cfg.workloads[0].duration_secs, 60);
assert_eq!(cfg.loop_count, 1);
}
#[test]
fn available_workloads_lists_v1_impls() {
assert!(AVAILABLE_WORKLOADS.contains(&"stress-ng-cpu"));
assert!(AVAILABLE_WORKLOADS.contains(&"y-cruncher-sse"));
assert!(AVAILABLE_WORKLOADS.contains(&"y-cruncher-avx2"));
assert!(AVAILABLE_WORKLOADS.contains(&"7zip-bench"));
assert!(AVAILABLE_WORKLOADS.contains(&"c2c-latency"));
assert!(AVAILABLE_WORKLOADS.contains(&"dram-latency"));
// Deferred impl NOT in the list (minecraft).
assert!(!AVAILABLE_WORKLOADS.contains(&"minecraft-server"));
}
}