perf_timer/
lib.rs

1#![cfg_attr(not(test), no_std)]
2
3mod arch;
4
5use core::time::Duration;
6
7pub use arch::{Arch, ArchFunctionality};
8
9/// This struct is used to calculate the duration between two instant.
10///
11/// # Example
12/// ```no_run
13/// use perf_timer::Instant;
14///
15/// let start = Instant::now();
16///
17/// // ...
18///
19/// let duration = start.elapsed();
20/// ```
21pub struct Instant {
22    cpu_count: u64,
23    frequency: u64,
24}
25
26impl Instant {
27    /// Create a new instant.
28    pub fn now() -> Self {
29        Self::from_cpu_count(Arch::cpu_count())
30    }
31
32    /// Create a new instant from a cpu count.
33    pub fn from_cpu_count(cpu_count: u64) -> Self {
34        Self { cpu_count, frequency: Arch::perf_frequency() }
35    }
36
37    /// Create a new instant from the start of the counter.
38    pub fn beginning() -> Self {
39        Self { cpu_count: Arch::cpu_count_start(), frequency: Arch::perf_frequency() }
40    }
41
42    /// Return the amount of time from `earlier` adn this instant.
43    ///
44    /// # Panic
45    /// This function will panic if earlier is not in the past.
46    pub fn duration_since(&self, earlier: &Self) -> Duration {
47        if earlier.cpu_count > self.cpu_count {
48            panic!("earlier not in the past.");
49        }
50        let diff = (self.cpu_count - earlier.cpu_count) as f64;
51        Duration::from_secs_f64(diff / self.frequency as f64)
52    }
53
54    /// Return the amount of time that elapsed since now and this instant.
55    pub fn elapsed(&self) -> Duration {
56        Instant::now().duration_since(self)
57    }
58}
59
60#[cfg(test)]
61mod test {
62    use super::*;
63    use std::thread;
64
65    #[ignore = "Register / instruction return nonsense in the Azure pipeline vm."]
66    #[test]
67    fn test_instant() {
68        let ns = 1_000_000_000;
69
70        let start = Instant::now();
71        thread::sleep(Duration::from_nanos(ns));
72        let duration = start.elapsed();
73
74        let precision = (duration.as_nanos() as u64 - ns) as f64 / ns as f64 * 100_f64;
75        assert!(precision < 0.1, "precision is: {precision}");
76    }
77}