1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
//! Maybe the simplest time taking crate there is. //! //! The `timed!` macro prints the labels as `{:<26}` (left aligned, 26 char length). The only //! reason `26` is chosen is because my longest label happend to be around 26 chars long. //! The timings are printed as floating points in microseconds, for much of the same reasons. //! The exact print format is hardcoded as: //! //! ``` //! # let t1 = 1; let t0 = 0; let label = "hei"; //! println!("[timed] {:<26} {:9.4}ms", label, (t1 - t0) as f64 / 1_000_000.0); //! ``` //! //! # Examples //! //! The crate has a macro `timed!` which is used for timing a block: //! //! ``` //! # #[macro_use] extern crate tid; //! # fn main() { //! timed!("pushing some stuff", //! let mut v = Vec::new(); //! for i in 0..100 { //! v.push(i); //! }; // note the `;` here //! ); //! let q = v; // `v` is still reachable out here. //! # } //! ``` //! //! If you have multiple consecutive blocks, you can use `Timer` instead. //! //! ``` //! # use tid::Timer; //! # fn f() { } //! # fn g() { } //! # fn h() { } //! let mut t = Timer::new(); //! f(); //! t.mark("Doing f"); //! g(); //! t.mark("G is executed"); //! h(); //! t.mark("Done with H"); //! t.present(); //! ``` //! extern crate time; #[macro_export] /// Time a block of code. For macro reasons, all blocks must be terminated by `;`. macro_rules! timed { ($name:expr, $($block:stmt);+;) => ( let t0 = $crate::_time(); $($block);+; let t1 = $crate::_time(); println!("[timed] {:<26} {:9.4}ms", $name, (t1 - t0) as f64 / 1_000_000.0); ) } #[doc(hidden)] // Wrap `time::precise_time_ns` so the crate using `tid` doesn't have to depend on `time`. // Maybe there is a better way to do this? pub fn _time() -> u64 { time::precise_time_ns() } /// A `Timer` is used for timing multiple consecutive sections of your code. The first timing is /// done when the object is constructed. The second timing is done at the first call to `mark`. /// This time difference will be the one reported with the label you pass to `mark`. /// /// # Examples /// /// ``` /// # use tid::Timer; /// # fn f() { } /// # fn g() { } /// # fn h() { } /// let mut t = Timer::new(); /// f(); /// t.mark("Doing f"); /// g(); /// t.mark("G is executed"); /// h(); /// t.mark("Done with H"); /// t.present(); /// ``` /// /// When `present` is called, we print all timings: /// /// ```text /// [timer] Doing f 0.12004ms /// [timer] G is executed 21.98122ms /// [timer] Done with H 7.00124ms /// ``` pub struct Timer { times: Vec<u64>, strs: Vec<&'static str>, } impl Timer { /// Create a new `Timer`. The first time sample is taken here. pub fn new() -> Self { let mut s = Self { times: Vec::with_capacity(100), strs: Vec::with_capacity(100), }; s.times.push(time::precise_time_ns()); s } /// Mark off a secion with the given label. pub fn mark(&mut self, label: &'static str) { self.times.push(time::precise_time_ns()); self.strs.push(label); } /// Print out the timings to `stdout`. pub fn present(self) { let diffs = self.times.iter().zip(self.times.iter().skip(1)).map( |(a, b)| { b - a }, ); for (time, s) in diffs.zip(self.strs.iter()) { println!("\t[timer] {:<26} {:9.4}ms", s, time as f64 / 1_000_000.0); } } }