use super::*;
static F_BORROW: &[&flags::FlagDecl] = &[&flags::BORROW_DECL];
static F_LLC: &[&flags::FlagDecl] = &[&flags::LLC_DECL];
static F_REBAL: &[&flags::FlagDecl] = &[&flags::REBAL_DECL];
static F_REJECT_PIN: &[&flags::FlagDecl] = &[&flags::REJECT_PIN_DECL];
static F_NO_CTRL: &[&flags::FlagDecl] = &[&flags::NO_CTRL_DECL];
static F_LLC_STEAL: &[&flags::FlagDecl] = &[&flags::LLC_DECL, &flags::STEAL_DECL];
static F_LLC_REBAL: &[&flags::FlagDecl] = &[&flags::LLC_DECL, &flags::REBAL_DECL];
static F_BORROW_REBAL: &[&flags::FlagDecl] = &[&flags::BORROW_DECL, &flags::REBAL_DECL];
static F_NO_CTRL_BORROW: &[&flags::FlagDecl] = &[&flags::NO_CTRL_DECL, &flags::BORROW_DECL];
static F_NO_CTRL_REBAL: &[&flags::FlagDecl] = &[&flags::NO_CTRL_DECL, &flags::REBAL_DECL];
macro_rules! s {
($name:expr, $cat:expr, $desc:expr, $cgroups:expr, $cpuset:expr, $works:expr) => {
Scenario {
name: $name,
category: $cat,
description: $desc,
required_flags: &[],
excluded_flags: &[],
num_cgroups: $cgroups,
cpuset_mode: $cpuset,
cgroup_works: $works,
action: Action::Steady,
}
};
}
macro_rules! custom {
($name:expr, $cat:expr, $desc:expr, $fn:expr) => {
Scenario {
name: $name,
category: $cat,
description: $desc,
required_flags: &[],
excluded_flags: &[],
num_cgroups: 0,
cpuset_mode: CpusetMode::None,
cgroup_works: vec![],
action: Action::Custom($fn),
}
};
}
pub fn all_scenarios() -> Vec<Scenario> {
use super::affinity::*;
use super::basic::*;
use super::cpuset::*;
use super::dynamic::*;
use super::interaction::*;
use super::nested::*;
use super::performance::*;
use super::stress::*;
let dfl = || vec![CgroupWork::default()];
let w = |wt, pol| {
vec![CgroupWork {
work_type: wt,
policy: pol,
..Default::default()
}]
};
let aff = |a| {
vec![CgroupWork {
affinity: a,
..Default::default()
}]
};
vec![
s!(
"cgroup_steady",
"basic",
"2 cgroups, no cpusets, equal load",
2,
CpusetMode::None,
dfl()
),
s!(
"cgroup_cpuset_llc_steady",
"basic",
"2 cgroups, LLC-aligned cpusets, equal load",
2,
CpusetMode::LlcAligned,
dfl()
),
s!(
"cgroup_cpuset_crossllc_steady",
"basic",
"2 cgroups, cpusets spanning LLC boundary",
2,
CpusetMode::SplitMisaligned,
dfl()
),
s!(
"cgroup_cpuset_overlap_steady",
"cpuset",
"3 cgroups, 50% overlapping cpusets",
3,
CpusetMode::Overlap(0.5),
dfl()
),
s!(
"cgroup_partial_cpus_steady",
"stress",
"2 cgroups, 1/3 CPUs unused",
2,
CpusetMode::Holdback(0.33),
dfl()
),
s!(
"cgroup_uneven_steady",
"stress",
"2 cgroups, 75/25 CPU split",
2,
CpusetMode::Uneven(0.75),
dfl()
),
s!(
"cgroup_oversubscribed",
"stress",
"2 cgroups, 32 mixed workers >> CPUs",
2,
CpusetMode::None,
vec![CgroupWork {
num_workers: Some(32),
work_type: WorkType::Mixed,
..Default::default()
}]
),
s!(
"cgroup_affinity_inherit",
"affinity",
"No explicit affinity, mixed workload",
2,
CpusetMode::None,
w(WorkType::Mixed, SchedPolicy::Normal)
),
s!(
"cgroup_affinity_random",
"affinity",
"Random CPU subset per worker",
2,
CpusetMode::SplitHalf,
aff(AffinityKind::RandomSubset)
),
s!(
"cgroup_affinity_spanning",
"affinity",
"Affinity mask covers all CPUs",
2,
CpusetMode::SplitHalf,
aff(AffinityKind::CrossCgroup)
),
s!(
"cgroup_affinity_pinned",
"affinity",
"One CPU per worker",
2,
CpusetMode::SplitHalf,
aff(AffinityKind::SingleCpu)
),
s!(
"sched_batch",
"sched_class",
"SCHED_BATCH workers",
2,
CpusetMode::None,
w(WorkType::CpuSpin, SchedPolicy::Batch)
),
s!(
"sched_idle",
"sched_class",
"SCHED_IDLE workers",
2,
CpusetMode::None,
w(WorkType::CpuSpin, SchedPolicy::Idle)
),
s!(
"sched_fifo",
"sched_class",
"RT SCHED_FIFO + normal workers",
2,
CpusetMode::None,
vec![CgroupWork {
num_workers: Some(1),
policy: SchedPolicy::Fifo(1),
work_type: WorkType::Bursty {
burst_ms: 500,
sleep_ms: 250
},
..Default::default()
}]
),
s!(
"sched_rr",
"sched_class",
"RT SCHED_RR + normal workers",
2,
CpusetMode::None,
vec![CgroupWork {
num_workers: Some(2),
policy: SchedPolicy::RoundRobin(1),
work_type: WorkType::Bursty {
burst_ms: 500,
sleep_ms: 250
},
..Default::default()
}]
),
Scenario {
name: "cgroup_idle_overloaded",
category: "advanced",
description: "One cgroup idle, other overloaded",
required_flags: F_BORROW,
excluded_flags: &[],
num_cgroups: 2,
cpuset_mode: CpusetMode::None,
cgroup_works: vec![
CgroupWork {
num_workers: Some(16),
..Default::default()
},
CgroupWork {
num_workers: Some(0),
..Default::default()
},
],
action: Action::Steady,
},
Scenario {
name: "cgroup_all_loaded",
category: "advanced",
description: "All cgroups loaded, idle CPUs contested",
required_flags: F_BORROW,
excluded_flags: &[],
num_cgroups: 2,
cpuset_mode: CpusetMode::None,
cgroup_works: vec![CgroupWork {
num_workers: Some(16),
..Default::default()
}],
action: Action::Steady,
},
Scenario {
name: "cgroup_llc_overflow",
category: "advanced",
description: "Single overloaded cgroup, cross-LLC migration",
required_flags: F_LLC_STEAL,
excluded_flags: &[],
num_cgroups: 1,
cpuset_mode: CpusetMode::None,
cgroup_works: vec![CgroupWork {
num_workers: Some(8),
..Default::default()
}],
action: Action::Steady,
},
Scenario {
name: "cgroup_load_imbalance",
category: "advanced",
description: "Heavy + light cgroups",
required_flags: F_REBAL,
excluded_flags: &[],
num_cgroups: 2,
cpuset_mode: CpusetMode::None,
cgroup_works: vec![
CgroupWork {
num_workers: Some(16),
..Default::default()
},
CgroupWork {
num_workers: Some(1),
work_type: WorkType::YieldHeavy,
..Default::default()
},
],
action: Action::Steady,
},
Scenario {
name: "stall_detect",
category: "stall",
description: "Overloaded single cgroup",
required_flags: &[],
excluded_flags: &[],
num_cgroups: 1,
cpuset_mode: CpusetMode::None,
cgroup_works: vec![CgroupWork {
num_workers: Some(16),
..Default::default()
}],
action: Action::Steady,
},
Scenario {
name: "cgroup_cpuset_llc_affinity",
category: "affinity",
description: "LLC-aligned affinity + cpusets",
required_flags: F_LLC,
excluded_flags: &[],
num_cgroups: 2,
cpuset_mode: CpusetMode::LlcAligned,
cgroup_works: aff(AffinityKind::LlcAligned),
action: Action::Steady,
},
Scenario {
name: "cgroup_affinity_change",
category: "affinity",
description: "Affinities randomized mid-run",
required_flags: &[],
excluded_flags: F_REJECT_PIN,
num_cgroups: 2,
cpuset_mode: CpusetMode::None,
cgroup_works: dfl(),
action: Action::Custom(custom_cgroup_affinity_change),
},
custom!(
"cgroup_add_midrun",
"dynamic",
"Add cgroups to running system",
custom_cgroup_add_midrun
),
custom!(
"cgroup_remove_midrun",
"dynamic",
"Remove cgroups mid-run",
custom_cgroup_remove_midrun
),
custom!(
"cgroup_rapid_churn",
"dynamic",
"Rapid create/destroy cycling",
custom_cgroup_rapid_churn
),
custom!(
"cgroup_cpuset_apply_midrun",
"cpuset",
"Add cpusets to running cgroups",
custom_cgroup_cpuset_apply_midrun
),
custom!(
"cgroup_cpuset_clear_midrun",
"cpuset",
"Clear cpusets from running cgroups",
custom_cgroup_cpuset_clear_midrun
),
custom!(
"cgroup_cpuset_resize",
"cpuset",
"Shrink then grow cpusets on live cgroups",
custom_cgroup_cpuset_resize
),
custom!(
"host_cgroup_contention",
"stress",
"Host workers competing with cgroup workers",
custom_host_cgroup_contention
),
custom!(
"cgroup_per_cpu",
"stress",
"One cgroup per CPU",
custom_cgroup_per_cpu
),
custom!(
"cgroup_exhaust_reuse",
"advanced",
"Fill cgroups, remove half, create replacements",
custom_cgroup_exhaust_reuse
),
custom!(
"sched_mixed",
"sched_class",
"Mix of all sched classes",
custom_sched_mixed
),
custom!(
"cgroup_pipe_io",
"sched_class",
"Pipe-paired IO + CPU workers",
custom_cgroup_pipe_io
),
Scenario {
name: "stall_recovery",
category: "stall",
description: "Scheduler restart recovery",
required_flags: &[],
excluded_flags: &[],
num_cgroups: 2,
cpuset_mode: CpusetMode::None,
cgroup_works: vec![CgroupWork {
num_workers: Some(16),
..Default::default()
}],
action: Action::Steady,
},
custom!(
"nested_cgroup_steady",
"nested",
"Workers in nested sub-cgroups",
custom_nested_cgroup_steady
),
custom!(
"nested_cgroup_task_move",
"nested",
"Move tasks between nested cgroups",
custom_nested_cgroup_task_move
),
custom!(
"nested_cgroup_rapid_churn",
"nested",
"Rapid nested cgroup create/destroy",
custom_nested_cgroup_rapid_churn
),
custom!(
"nested_cgroup_cpuset",
"nested",
"Nested cgroups with restrictive cpusets",
custom_nested_cgroup_cpuset
),
Scenario {
name: "cgroup_cpuset_workload_imbalance",
category: "advanced",
description: "Imbalanced load with cpuset-constrained cgroups",
required_flags: F_BORROW,
excluded_flags: &[],
num_cgroups: 0,
cpuset_mode: CpusetMode::None,
cgroup_works: vec![],
action: Action::Custom(custom_cgroup_cpuset_workload_imbalance),
},
Scenario {
name: "cgroup_cpuset_load_shift",
category: "advanced",
description: "Imbalanced load with cpusets, then add heavy",
required_flags: F_REBAL,
excluded_flags: &[],
num_cgroups: 0,
cpuset_mode: CpusetMode::None,
cgroup_works: vec![],
action: Action::Custom(custom_cgroup_cpuset_load_shift),
},
Scenario {
name: "cgroup_add_load_imbalance",
category: "advanced",
description: "Light cgroups then heavy added mid-run",
required_flags: F_REBAL,
excluded_flags: &[],
num_cgroups: 0,
cpuset_mode: CpusetMode::None,
cgroup_works: vec![],
action: Action::Custom(custom_cgroup_add_load_imbalance),
},
Scenario {
name: "cgroup_imbalance_mixed_workload",
category: "advanced",
description: "Heavy + bursty + IO cgroups",
required_flags: F_BORROW_REBAL,
excluded_flags: &[],
num_cgroups: 0,
cpuset_mode: CpusetMode::None,
cgroup_works: vec![],
action: Action::Custom(custom_cgroup_imbalance_mixed_workload),
},
Scenario {
name: "cgroup_multicpu_pin",
category: "advanced",
description: "Workers pinned to 2 CPUs each",
required_flags: F_REJECT_PIN,
excluded_flags: &[],
num_cgroups: 0,
cpuset_mode: CpusetMode::None,
cgroup_works: vec![],
action: Action::Custom(custom_cgroup_multicpu_pin),
},
Scenario {
name: "cgroup_noctrl_task_migration",
category: "advanced",
description: "Rapid per-task moves without controller",
required_flags: F_NO_CTRL,
excluded_flags: &[],
num_cgroups: 0,
cpuset_mode: CpusetMode::None,
cgroup_works: vec![],
action: Action::Custom(custom_cgroup_noctrl_task_migration),
},
Scenario {
name: "cgroup_cpuset_change_imbalance",
category: "advanced",
description: "Cpuset resize during imbalanced load",
required_flags: F_BORROW,
excluded_flags: &[],
num_cgroups: 0,
cpuset_mode: CpusetMode::None,
cgroup_works: vec![],
action: Action::Custom(custom_cgroup_cpuset_change_imbalance),
},
Scenario {
name: "cgroup_load_oscillation",
category: "advanced",
description: "Alternating heavy/light cgroups",
required_flags: F_REBAL,
excluded_flags: &[],
num_cgroups: 0,
cpuset_mode: CpusetMode::None,
cgroup_works: vec![],
action: Action::Custom(custom_cgroup_load_oscillation),
},
Scenario {
name: "nested_cgroup_noctrl",
category: "advanced",
description: "Nested cgroups without controller",
required_flags: F_NO_CTRL,
excluded_flags: &[],
num_cgroups: 0,
cpuset_mode: CpusetMode::None,
cgroup_works: vec![],
action: Action::Custom(custom_nested_cgroup_noctrl),
},
Scenario {
name: "cgroup_cpuset_swap_disjoint",
category: "cpuset",
description: "Swap cpusets to non-overlapping ranges",
required_flags: &[],
excluded_flags: &[],
num_cgroups: 0,
cpuset_mode: CpusetMode::None,
cgroup_works: vec![],
action: Action::Custom(custom_cgroup_cpuset_swap_disjoint),
},
Scenario {
name: "cgroup_io_compute_imbalance",
category: "advanced",
description: "IO cgroup frees CPUs for compute cgroup",
required_flags: F_BORROW,
excluded_flags: &[],
num_cgroups: 0,
cpuset_mode: CpusetMode::None,
cgroup_works: vec![],
action: Action::Custom(custom_cgroup_io_compute_imbalance),
},
Scenario {
name: "cgroup_4way_load_imbalance",
category: "advanced",
description: "4 cgroups with asymmetric demand",
required_flags: F_REBAL,
excluded_flags: &[],
num_cgroups: 0,
cpuset_mode: CpusetMode::None,
cgroup_works: vec![],
action: Action::Custom(custom_cgroup_4way_load_imbalance),
},
Scenario {
name: "cgroup_cpuset_overlap_imbalance",
category: "advanced",
description: "Imbalanced load with overlapping cpusets",
required_flags: F_BORROW,
excluded_flags: &[],
num_cgroups: 3,
cpuset_mode: CpusetMode::Overlap(0.5),
cgroup_works: vec![
CgroupWork {
num_workers: Some(8),
..Default::default()
},
CgroupWork {
num_workers: Some(1),
work_type: WorkType::Bursty {
burst_ms: 50,
sleep_ms: 100,
},
..Default::default()
},
CgroupWork {
num_workers: Some(1),
work_type: WorkType::YieldHeavy,
..Default::default()
},
],
action: Action::Steady,
},
Scenario {
name: "cgroup_cpuset_overlap_load_imbalance",
category: "advanced",
description: "Imbalanced load with overlapping cpusets, rebalancing",
required_flags: F_REBAL,
excluded_flags: &[],
num_cgroups: 3,
cpuset_mode: CpusetMode::Overlap(0.5),
cgroup_works: vec![
CgroupWork {
num_workers: Some(16),
..Default::default()
},
CgroupWork {
num_workers: Some(1),
work_type: WorkType::YieldHeavy,
..Default::default()
},
CgroupWork {
num_workers: Some(4),
..Default::default()
},
],
action: Action::Steady,
},
Scenario {
name: "cgroup_bursty_imbalance",
category: "advanced",
description: "Steady + bursty cgroups",
required_flags: F_BORROW,
excluded_flags: &[],
num_cgroups: 2,
cpuset_mode: CpusetMode::None,
cgroup_works: vec![
CgroupWork {
num_workers: Some(8),
..Default::default()
},
CgroupWork {
num_workers: Some(4),
work_type: WorkType::Bursty {
burst_ms: 50,
sleep_ms: 100,
},
..Default::default()
},
],
action: Action::Steady,
},
Scenario {
name: "cgroup_bursty_load_shift",
category: "advanced",
description: "Bursty heavy + steady light cgroups",
required_flags: F_REBAL,
excluded_flags: &[],
num_cgroups: 2,
cpuset_mode: CpusetMode::None,
cgroup_works: vec![
CgroupWork {
num_workers: Some(12),
work_type: WorkType::Bursty {
burst_ms: 200,
sleep_ms: 50,
},
..Default::default()
},
CgroupWork {
num_workers: Some(4),
..Default::default()
},
],
action: Action::Steady,
},
Scenario {
name: "cgroup_cpuset_imbalance_combined",
category: "interaction",
description: "Imbalanced load with cpusets, work conservation + rebalancing",
required_flags: F_BORROW_REBAL,
excluded_flags: &[],
num_cgroups: 0,
cpuset_mode: CpusetMode::None,
cgroup_works: vec![],
action: Action::Custom(custom_cgroup_cpuset_imbalance_combined),
},
Scenario {
name: "cgroup_cpuset_overlap_imbalance_combined",
category: "interaction",
description: "Imbalanced load with overlapping cpusets, work conservation + rebalancing",
required_flags: F_BORROW_REBAL,
excluded_flags: &[],
num_cgroups: 0,
cpuset_mode: CpusetMode::None,
cgroup_works: vec![],
action: Action::Custom(custom_cgroup_cpuset_overlap_imbalance_combined),
},
Scenario {
name: "cgroup_noctrl_imbalance",
category: "interaction",
description: "Per-task moves during imbalanced load without controller",
required_flags: F_NO_CTRL_BORROW,
excluded_flags: &[],
num_cgroups: 0,
cpuset_mode: CpusetMode::None,
cgroup_works: vec![],
action: Action::Custom(custom_cgroup_noctrl_imbalance),
},
Scenario {
name: "cgroup_noctrl_cpuset_change",
category: "interaction",
description: "Cpuset add/clear without controller",
required_flags: F_NO_CTRL,
excluded_flags: &[],
num_cgroups: 0,
cpuset_mode: CpusetMode::None,
cgroup_works: vec![],
action: Action::Custom(custom_cgroup_noctrl_cpuset_change),
},
Scenario {
name: "cgroup_noctrl_load_imbalance",
category: "interaction",
description: "Heavy + light cgroups without controller",
required_flags: F_NO_CTRL_REBAL,
excluded_flags: &[],
num_cgroups: 0,
cpuset_mode: CpusetMode::None,
cgroup_works: vec![],
action: Action::Custom(custom_cgroup_noctrl_load_imbalance),
},
Scenario {
name: "cgroup_cpuset_multicpu_pin",
category: "interaction",
description: "Multi-CPU pin within cpuset-constrained cgroups",
required_flags: F_REJECT_PIN,
excluded_flags: &[],
num_cgroups: 0,
cpuset_mode: CpusetMode::None,
cgroup_works: vec![],
action: Action::Custom(custom_cgroup_cpuset_multicpu_pin),
},
Scenario {
name: "cgroup_cpuset_add_remove",
category: "interaction",
description: "Add/remove cpuset-constrained cgroups",
required_flags: &[],
excluded_flags: &[],
num_cgroups: 0,
cpuset_mode: CpusetMode::None,
cgroup_works: vec![],
action: Action::Custom(custom_cgroup_cpuset_add_remove),
},
Scenario {
name: "cgroup_add_during_imbalance",
category: "interaction",
description: "Add cgroup during imbalanced load",
required_flags: F_BORROW,
excluded_flags: &[],
num_cgroups: 0,
cpuset_mode: CpusetMode::None,
cgroup_works: vec![],
action: Action::Custom(custom_cgroup_add_during_imbalance),
},
Scenario {
name: "nested_cgroup_imbalance",
category: "interaction",
description: "Nested cgroups with imbalanced load",
required_flags: F_BORROW,
excluded_flags: &[],
num_cgroups: 0,
cpuset_mode: CpusetMode::None,
cgroup_works: vec![],
action: Action::Custom(custom_nested_cgroup_imbalance),
},
custom!(
"cgroup_dsq_contention",
"stress",
"Bursty + pinned workers on shared DSQ",
custom_cgroup_dsq_contention
),
custom!(
"cgroup_workload_variety",
"stress",
"5 cgroups, 5 workload types",
custom_cgroup_workload_variety
),
custom!(
"cgroup_cpuset_workload_variety",
"stress",
"Diverse workloads with cpuset partitioning",
custom_cgroup_cpuset_workload_variety
),
custom!(
"cgroup_dynamic_workload_variety",
"stress",
"Diverse workloads with cgroup add/remove",
custom_cgroup_dynamic_workload_variety
),
Scenario {
name: "cgroup_cpuset_crossllc_race",
category: "stress",
description: "Rapid cpuset flips across LLC boundaries",
required_flags: F_LLC_REBAL,
excluded_flags: &[],
num_cgroups: 0,
cpuset_mode: CpusetMode::None,
cgroup_works: vec![],
action: Action::Custom(custom_cgroup_cpuset_crossllc_race),
},
Scenario {
name: "cache_pressure_imbalance",
category: "performance",
description: "CachePressure vs CpuSpin cgroups",
required_flags: F_BORROW,
excluded_flags: &[],
num_cgroups: 0,
cpuset_mode: CpusetMode::None,
cgroup_works: vec![],
action: Action::Custom(custom_cache_pressure_imbalance),
},
Scenario {
name: "cache_yield_wake_affine",
category: "performance",
description: "CacheYield workers testing wake-affine placement",
required_flags: F_LLC,
excluded_flags: &[],
num_cgroups: 0,
cpuset_mode: CpusetMode::None,
cgroup_works: vec![],
action: Action::Custom(custom_cache_yield_wake_affine),
},
Scenario {
name: "cache_pipe_io_compute_imbalance",
category: "performance",
description: "CachePipe vs CpuSpin cgroups",
required_flags: F_BORROW,
excluded_flags: &[],
num_cgroups: 0,
cpuset_mode: CpusetMode::None,
cgroup_works: vec![],
action: Action::Custom(custom_cache_pipe_io_compute_imbalance),
},
Scenario {
name: "fanout_wake",
category: "performance",
description: "1:N futex fan-out wake vs compute workers",
required_flags: F_BORROW,
excluded_flags: &[],
num_cgroups: 0,
cpuset_mode: CpusetMode::None,
cgroup_works: vec![],
action: Action::Custom(custom_fanout_wake),
},
]
}