| 1 | use std::io::{self, Write};
 | 
|---|
| 2 | use std::sync::atomic::{AtomicU64, AtomicBool, Ordering};
 | 
|---|
| 3 | use std::time::{Instant,Duration};
 | 
|---|
| 4 | 
 | 
|---|
| 5 | use clap::{Arg, ArgMatches};
 | 
|---|
| 6 | use isatty::stdout_isatty;
 | 
|---|
| 7 | 
 | 
|---|
| 8 | use tokio::time;
 | 
|---|
| 9 | 
 | 
|---|
| 10 | 
 | 
|---|
| 11 | // ==================================================
 | 
|---|
| 12 | pub fn args<'a, 'b>() -> [Arg<'a, 'b>; 4] {[
 | 
|---|
| 13 |         Arg::with_name("duration")  .short("d").long("duration")  .takes_value(true).default_value("5").help("Duration of the experiments in seconds"),
 | 
|---|
| 14 |         Arg::with_name("iterations").short("i").long("iterations").takes_value(true).conflicts_with("duration").help("Number of iterations of the experiments"),
 | 
|---|
| 15 |         Arg::with_name("nthreads")  .short("t").long("nthreads")  .takes_value(true).default_value("1").help("Number of threads to use"),
 | 
|---|
| 16 |         Arg::with_name("nprocs")    .short("p").long("nprocs")    .takes_value(true).default_value("1").help("Number of processors to use")
 | 
|---|
| 17 | ]}
 | 
|---|
| 18 | 
 | 
|---|
| 19 | pub struct BenchData {
 | 
|---|
| 20 |         pub clock_mode: bool,
 | 
|---|
| 21 |         pub stop: AtomicBool,
 | 
|---|
| 22 |         pub stop_count: u64,
 | 
|---|
| 23 |         pub duration: f64,
 | 
|---|
| 24 |         pub threads_left: AtomicU64,
 | 
|---|
| 25 |         is_tty: bool,
 | 
|---|
| 26 | }
 | 
|---|
| 27 | 
 | 
|---|
| 28 | impl BenchData {
 | 
|---|
| 29 |         pub fn new(options: ArgMatches, nthreads: usize) -> BenchData {
 | 
|---|
| 30 |                 let (clock_mode, stop_count, duration) = if options.is_present("iterations") {
 | 
|---|
| 31 |                         (false,
 | 
|---|
| 32 |                         options.value_of("iterations").unwrap().parse::<u64>().unwrap(),
 | 
|---|
| 33 |                         -1.0)
 | 
|---|
| 34 |                 } else {
 | 
|---|
| 35 |                         (true,
 | 
|---|
| 36 |                         std::u64::MAX,
 | 
|---|
| 37 |                         options.value_of("duration").unwrap().parse::<f64>().unwrap())
 | 
|---|
| 38 |                 };
 | 
|---|
| 39 | 
 | 
|---|
| 40 |                 BenchData{
 | 
|---|
| 41 |                         clock_mode: clock_mode,
 | 
|---|
| 42 |                         stop: AtomicBool::new(false),
 | 
|---|
| 43 |                         stop_count: stop_count,
 | 
|---|
| 44 |                         duration: duration,
 | 
|---|
| 45 |                         threads_left: AtomicU64::new(nthreads as u64),
 | 
|---|
| 46 |                         is_tty: stdout_isatty(),
 | 
|---|
| 47 |                 }
 | 
|---|
| 48 |         }
 | 
|---|
| 49 | 
 | 
|---|
| 50 |         pub async fn wait(&self, start: &Instant) -> Duration{
 | 
|---|
| 51 |                 loop {
 | 
|---|
| 52 |                         time::sleep(Duration::from_micros(100000)).await;
 | 
|---|
| 53 |                         let delta = start.elapsed();
 | 
|---|
| 54 |                         if self.is_tty {
 | 
|---|
| 55 |                                 print!(" {:.1}\r", delta.as_secs_f32());
 | 
|---|
| 56 |                                 io::stdout().flush().unwrap();
 | 
|---|
| 57 |                         }
 | 
|---|
| 58 |                         if self.clock_mode && delta >= Duration::from_secs_f64(self.duration)  {
 | 
|---|
| 59 |                                 break;
 | 
|---|
| 60 |                         }
 | 
|---|
| 61 |                         else if !self.clock_mode && self.threads_left.load(Ordering::Relaxed) == 0 {
 | 
|---|
| 62 |                                 break;
 | 
|---|
| 63 |                         }
 | 
|---|
| 64 |                 }
 | 
|---|
| 65 | 
 | 
|---|
| 66 |                 self.stop.store(true, Ordering::SeqCst);
 | 
|---|
| 67 |                 return start.elapsed();
 | 
|---|
| 68 |         }
 | 
|---|
| 69 | }
 | 
|---|
| 70 | 
 | 
|---|