use crate::request::{self, Request, RequestPlanner};
use std::{
io::{self, Write},
time::{Duration, Instant},
};
pub async fn benchmark(
requests: &[Request],
planner: &RequestPlanner,
target_index: usize,
count: usize,
) -> Result<(), Box<dyn std::error::Error>> {
println!(
"Benchmarking request: {}",
requests
.get(target_index)
.map(|req| req.description.as_str())
.unwrap_or("<unknown>")
);
let plan = planner.order_for(target_index)?;
let mut bench_requests = requests.to_vec();
for idx in &plan {
if let Some(req) = bench_requests.get_mut(*idx) {
req.callback_src.clear();
}
}
let mut request_time: Vec<Duration> = vec![];
for i in 0..count {
let start = Instant::now();
request::execute_request_plan(&bench_requests, &plan, request::ExecutionOptions::default())
.await
.map_err(|err| -> Box<dyn std::error::Error> { Box::new(err) })?;
let duration = start.elapsed();
request_time.push(duration);
let progress = if count > 1 {
(i as f64 / (count - 1) as f64) * 100.0
} else {
100.0
};
print!("\r[");
for j in 0..50 {
if j as f64 / 50.0 <= progress / 100.0 {
print!("#");
} else {
print!(" ");
}
}
print!("] {:.2}%", progress);
io::stdout().flush().unwrap();
}
let mean_duration = request_time.iter().sum::<Duration>() / count as u32;
let variance = request_time
.iter()
.map(|x| (x.as_secs_f64() - mean_duration.as_secs_f64()).powi(2))
.sum::<f64>()
/ count as f64;
println!("\n");
println!("Mean Duration: {:?}", mean_duration);
println!("Variance (%): {:?}", variance * 100.0);
Ok(())
}