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