use std::io::{self, Write}; use std::sync::atomic::{AtomicU64, AtomicBool, Ordering}; use std::time::{Instant,Duration}; use clap::{Arg, ArgMatches}; use isatty::stdout_isatty; use tokio::time; // ================================================== pub fn args<'a, 'b>() -> [Arg<'a, 'b>; 4] {[ Arg::with_name("duration") .short("d").long("duration") .takes_value(true).default_value("5").help("Duration of the experiments in seconds"), Arg::with_name("iterations").short("i").long("iterations").takes_value(true).conflicts_with("duration").help("Number of iterations of the experiments"), Arg::with_name("nthreads") .short("t").long("nthreads") .takes_value(true).default_value("1").help("Number of threads to use"), Arg::with_name("nprocs") .short("p").long("nprocs") .takes_value(true).default_value("1").help("Number of processors to use") ]} pub struct BenchData { pub clock_mode: bool, pub stop: AtomicBool, pub stop_count: u64, pub duration: f64, pub threads_left: AtomicU64, is_tty: bool, } impl BenchData { pub fn new(options: ArgMatches, nthreads: usize) -> BenchData { let (clock_mode, stop_count, duration) = if options.is_present("iterations") { (false, options.value_of("iterations").unwrap().parse::().unwrap(), -1.0) } else { (true, std::u64::MAX, options.value_of("duration").unwrap().parse::().unwrap()) }; BenchData{ clock_mode: clock_mode, stop: AtomicBool::new(false), stop_count: stop_count, duration: duration, threads_left: AtomicU64::new(nthreads as u64), is_tty: stdout_isatty(), } } pub async fn wait(&self, start: &Instant) -> Duration{ loop { time::sleep(Duration::from_micros(100000)).await; let delta = start.elapsed(); if self.is_tty { print!(" {:.1}\r", delta.as_secs_f32()); io::stdout().flush().unwrap(); } if self.clock_mode && delta >= Duration::from_secs_f64(self.duration) { break; } else if !self.clock_mode && self.threads_left.load(Ordering::Relaxed) == 0 { break; } } self.stop.store(true, Ordering::SeqCst); return start.elapsed(); } }