bencher: add args duration and summarize_last (seconds)

This commit is contained in:
Joakim Frostegård 2024-01-03 17:36:04 +01:00
parent 7863782413
commit 85862f161a
4 changed files with 65 additions and 42 deletions

View file

@ -6,6 +6,7 @@ pub mod set;
use clap::{Parser, Subcommand}; use clap::{Parser, Subcommand};
use common::{CpuMode, Priority}; use common::{CpuMode, Priority};
use set::run_sets;
#[derive(Parser)] #[derive(Parser)]
#[command(author, version, about)] #[command(author, version, about)]
@ -23,6 +24,17 @@ struct Args {
/// Minimum benchmark priority /// Minimum benchmark priority
#[arg(long, default_value_t = Priority::Medium)] #[arg(long, default_value_t = Priority::Medium)]
min_priority: Priority, min_priority: Priority,
/// How long to run each load test for
#[arg(long, default_value_t = 60)]
duration: usize,
/// Only include data for last N seconds of load test runs.
///
/// Useful if the tracker/load tester combination is slow at reaching
/// maximum throughput
///
/// 0 = use data for whole run
#[arg(long, default_value_t = 0)]
summarize_last: usize,
#[command(subcommand)] #[command(subcommand)]
command: Command, command: Command,
} }
@ -39,13 +51,21 @@ fn main() {
match args.command { match args.command {
#[cfg(feature = "udp")] #[cfg(feature = "udp")]
Command::Udp(command) => command Command::Udp(command) => {
.run( let sets = command.sets(args.cpu_mode);
let load_test_gen = protocols::udp::UdpCommand::load_test_gen;
run_sets(
&command,
args.cpu_mode, args.cpu_mode,
args.min_cores, args.min_cores,
args.max_cores, args.max_cores,
args.min_priority, args.min_priority,
) args.duration,
.unwrap(), args.summarize_last,
sets,
load_test_gen,
);
}
} }
} }

View file

@ -13,7 +13,7 @@ use tempfile::NamedTempFile;
use crate::{ use crate::{
common::{simple_load_test_runs, CpuMode, Priority, TaskSetCpuList}, common::{simple_load_test_runs, CpuMode, Priority, TaskSetCpuList},
run::ProcessRunner, run::ProcessRunner,
set::{run_sets, SetConfig, Tracker}, set::{LoadTestRunnerParameters, SetConfig, Tracker},
}; };
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@ -50,29 +50,7 @@ pub struct UdpCommand {
} }
impl UdpCommand { impl UdpCommand {
pub fn run( pub fn sets(&self, cpu_mode: CpuMode) -> IndexMap<usize, SetConfig<UdpCommand, UdpTracker>> {
&self,
cpu_mode: CpuMode,
min_cores: Option<usize>,
max_cores: Option<usize>,
min_priority: Priority,
) -> anyhow::Result<()> {
let sets = self.sets(cpu_mode);
run_sets(
self,
cpu_mode,
min_cores,
max_cores,
min_priority,
sets,
|workers| Box::new(AquaticUdpLoadTestRunner { workers }),
);
Ok(())
}
fn sets(&self, cpu_mode: CpuMode) -> IndexMap<usize, SetConfig<UdpCommand, UdpTracker>> {
// Priorities are based on what has previously produced the best results // Priorities are based on what has previously produced the best results
indexmap::indexmap! { indexmap::indexmap! {
1 => SetConfig { 1 => SetConfig {
@ -264,6 +242,12 @@ impl UdpCommand {
}, },
} }
} }
pub fn load_test_gen(
parameters: LoadTestRunnerParameters,
) -> Box<dyn ProcessRunner<Command = UdpCommand>> {
Box::new(AquaticUdpLoadTestRunner { parameters })
}
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@ -434,7 +418,7 @@ impl ProcessRunner for ChihayaUdpRunner {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
struct AquaticUdpLoadTestRunner { struct AquaticUdpLoadTestRunner {
workers: usize, parameters: LoadTestRunnerParameters,
} }
impl ProcessRunner for AquaticUdpLoadTestRunner { impl ProcessRunner for AquaticUdpLoadTestRunner {
@ -448,8 +432,9 @@ impl ProcessRunner for AquaticUdpLoadTestRunner {
) -> anyhow::Result<Child> { ) -> anyhow::Result<Child> {
let mut c = aquatic_udp_load_test::config::Config::default(); let mut c = aquatic_udp_load_test::config::Config::default();
c.workers = self.workers as u8; c.workers = self.parameters.workers as u8;
c.duration = 60; c.duration = self.parameters.duration;
c.summarize_last = self.parameters.summarize_last;
c.requests.weight_connect = 0; c.requests.weight_connect = 0;
c.requests.weight_announce = 100; c.requests.weight_announce = 100;
@ -478,7 +463,7 @@ impl ProcessRunner for AquaticUdpLoadTestRunner {
fn keys(&self) -> IndexMap<String, String> { fn keys(&self) -> IndexMap<String, String> {
indexmap! { indexmap! {
"workers".to_string() => self.workers.to_string(), "workers".to_string() => self.parameters.workers.to_string(),
} }
} }
} }

View file

@ -45,7 +45,11 @@ pub struct RunConfig<C> {
} }
impl<C> RunConfig<C> { impl<C> RunConfig<C> {
pub fn run(self, command: &C) -> Result<RunSuccessResults, RunErrorResults<C>> { pub fn run(
self,
command: &C,
duration: usize,
) -> Result<RunSuccessResults, RunErrorResults<C>> {
let mut tracker_config_file = NamedTempFile::new().unwrap(); let mut tracker_config_file = NamedTempFile::new().unwrap();
let mut load_test_config_file = NamedTempFile::new().unwrap(); let mut load_test_config_file = NamedTempFile::new().unwrap();
@ -75,7 +79,7 @@ impl<C> RunConfig<C> {
} }
}; };
for _ in 0..59 { for _ in 0..(duration - 1) {
if let Ok(Some(status)) = tracker.0.try_wait() { if let Ok(Some(status)) = tracker.0.try_wait() {
return Err(RunErrorResults::new(self) return Err(RunErrorResults::new(self)
.set_tracker_outputs(tracker) .set_tracker_outputs(tracker)

View file

@ -10,6 +10,13 @@ use crate::{
run::{ProcessRunner, ProcessStats, RunConfig}, run::{ProcessRunner, ProcessStats, RunConfig},
}; };
#[derive(Debug, Clone, Copy)]
pub struct LoadTestRunnerParameters {
pub workers: usize,
pub duration: usize,
pub summarize_last: usize,
}
pub trait Tracker: ::std::fmt::Debug + Copy + Clone + ::std::hash::Hash { pub trait Tracker: ::std::fmt::Debug + Copy + Clone + ::std::hash::Hash {
fn name(&self) -> String; fn name(&self) -> String;
} }
@ -25,12 +32,14 @@ pub fn run_sets<C, F, I>(
min_cores: Option<usize>, min_cores: Option<usize>,
max_cores: Option<usize>, max_cores: Option<usize>,
min_priority: Priority, min_priority: Priority,
duration: usize,
summarize_last: usize,
mut set_configs: IndexMap<usize, SetConfig<C, I>>, mut set_configs: IndexMap<usize, SetConfig<C, I>>,
load_test_gen: F, load_test_gen: F,
) where ) where
C: ::std::fmt::Debug, C: ::std::fmt::Debug,
I: Tracker, I: Tracker,
F: Fn(usize) -> Box<dyn ProcessRunner<Command = C>>, F: Fn(LoadTestRunnerParameters) -> Box<dyn ProcessRunner<Command = C>>,
{ {
if let Some(min_cores) = min_cores { if let Some(min_cores) = min_cores {
set_configs.retain(|cores, _| *cores >= min_cores); set_configs.retain(|cores, _| *cores >= min_cores);
@ -59,7 +68,7 @@ pub fn run_sets<C, F, I>(
.sum::<usize>(); .sum::<usize>();
let (estimated_hours, estimated_minutes) = { let (estimated_hours, estimated_minutes) = {
let minutes = (total_num_runs * 67) / 60; let minutes = (total_num_runs * (duration + 7)) / 60;
(minutes / 60, minutes % 60) (minutes / 60, minutes % 60)
}; };
@ -96,13 +105,18 @@ pub fn run_sets<C, F, I>(
.clone() .clone()
.into_iter() .into_iter()
.map(|(workers, _, load_test_vcpus)| { .map(|(workers, _, load_test_vcpus)| {
let load_test_parameters = LoadTestRunnerParameters {
workers,
duration,
summarize_last,
};
LoadTestRunResults::produce( LoadTestRunResults::produce(
command, command,
&load_test_gen, &load_test_gen,
load_test_parameters,
implementation, implementation,
&tracker_run, &tracker_run,
tracker_vcpus.clone(), tracker_vcpus.clone(),
workers,
load_test_vcpus, load_test_vcpus,
) )
}) })
@ -188,26 +202,26 @@ impl LoadTestRunResults {
pub fn produce<C, F, I>( pub fn produce<C, F, I>(
command: &C, command: &C,
load_test_gen: &F, load_test_gen: &F,
load_test_parameters: LoadTestRunnerParameters,
implementation: I, implementation: I,
tracker_process: &Rc<dyn ProcessRunner<Command = C>>, tracker_process: &Rc<dyn ProcessRunner<Command = C>>,
tracker_vcpus: TaskSetCpuList, tracker_vcpus: TaskSetCpuList,
workers: usize,
load_test_vcpus: TaskSetCpuList, load_test_vcpus: TaskSetCpuList,
) -> Self ) -> Self
where where
C: ::std::fmt::Debug, C: ::std::fmt::Debug,
I: Tracker, I: Tracker,
F: Fn(usize) -> Box<dyn ProcessRunner<Command = C>>, F: Fn(LoadTestRunnerParameters) -> Box<dyn ProcessRunner<Command = C>>,
{ {
println!( println!(
"### {} run ({}) (load test workers: {}, cpus: {})", "### {} run ({}) (load test workers: {}, cpus: {})",
implementation.name(), implementation.name(),
tracker_process.info(), tracker_process.info(),
workers, load_test_parameters.workers,
load_test_vcpus.as_cpu_list() load_test_vcpus.as_cpu_list()
); );
let load_test_runner = load_test_gen(workers); let load_test_runner = load_test_gen(load_test_parameters);
let load_test_keys = load_test_runner.keys(); let load_test_keys = load_test_runner.keys();
let run_config = RunConfig { let run_config = RunConfig {
@ -217,7 +231,7 @@ impl LoadTestRunResults {
load_test_vcpus: load_test_vcpus.clone(), load_test_vcpus: load_test_vcpus.clone(),
}; };
match run_config.run(command) { match run_config.run(command, load_test_parameters.duration) {
Ok(r) => { Ok(r) => {
println!( println!(
"- Average responses per second: {}", "- Average responses per second: {}",