use anyhow::Result; pub trait Workload { /// Starts the workload with specified threads and load percentage. fn start(&mut self, threads: usize, load_percent: usize) -> Result<()>; /// Stops the workload. fn stop(&mut self) -> Result<()>; /// Returns the current throughput (e.g., ops/sec). fn get_throughput(&self) -> Result; } pub struct StressNg { child: Option, } impl StressNg { pub fn new() -> Self { Self { child: None } } } impl Workload for StressNg { fn start(&mut self, threads: usize, load_percent: usize) -> Result<()> { self.stop()?; // Ensure any previous instance is stopped let child = std::process::Command::new("stress-ng") .args([ "--cpu", &threads.to_string(), "--cpu-load", &load_percent.to_string(), "--quiet" ]) .spawn()?; self.child = Some(child); Ok(()) } fn stop(&mut self) -> Result<()> { if let Some(mut child) = self.child.take() { let _ = child.kill(); let _ = child.wait(); } Ok(()) } fn get_throughput(&self) -> Result { // In a real implementation, we would parse stress-ng's temporary results // or use a different workload that provides live throughput. Ok(0.0) } } impl Drop for StressNg { fn drop(&mut self) { let _ = self.stop(); } }