Skip to main content

diskann_benchmark_runner/utils/
microseconds.rs

1/*
2 * Copyright (c) Microsoft Corporation.
3 * Licensed under the MIT license.
4 */
5
6use serde::{Deserialize, Serialize};
7
8use super::percentiles::AsF64Lossy;
9
10/// A unit of time representing microseconds.
11#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord)]
12#[serde(transparent)]
13pub struct MicroSeconds(u64);
14
15impl MicroSeconds {
16    /// Construct a new instance of self over a raw unit of micro-seconds.
17    pub fn new(micros: u64) -> Self {
18        Self(micros)
19    }
20
21    /// Return `self` as seconds.
22    pub fn as_seconds(self) -> f64 {
23        (self.0 as f64) / 1_000_000.0
24    }
25
26    /// Return `self` as microseconds.
27    pub fn as_micros(self) -> u64 {
28        self.0
29    }
30
31    /// Return `self` as microseconds but converted to `f64`.
32    pub fn as_f64(self) -> f64 {
33        self.0 as f64
34    }
35}
36
37impl From<std::time::Duration> for MicroSeconds {
38    fn from(value: std::time::Duration) -> Self {
39        Self::new(value.as_micros() as u64)
40    }
41}
42
43impl std::fmt::Display for MicroSeconds {
44    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
45        write!(f, "{}us", self.as_micros())
46    }
47}
48
49impl std::ops::Add for MicroSeconds {
50    type Output = Self;
51
52    fn add(self, rhs: Self) -> Self {
53        Self(self.0 + rhs.0)
54    }
55}
56
57impl std::iter::Sum for MicroSeconds {
58    fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
59        let sum: u64 = iter.map(|i| i.0).sum();
60        Self(sum)
61    }
62}
63
64impl AsF64Lossy for MicroSeconds {
65    fn as_f64_lossy(self) -> f64 {
66        self.as_f64()
67    }
68}
69
70#[doc(hidden)]
71#[macro_export]
72macro_rules! timed {
73    ($($exprs:tt)*) => {{
74        let start = ::std::time::Instant::now();
75        let result = $($exprs)*;
76        let elapsed: $crate::utils::MicroSeconds = start.elapsed().into();
77        (elapsed, result)
78    }}
79}
80
81///////////
82// Tests //
83///////////
84
85#[cfg(test)]
86mod tests {
87    use super::*;
88
89    #[test]
90    fn test_microseconds() {
91        let x = MicroSeconds::new(1_000_001);
92        assert_eq!(x.as_micros(), 1_000_001);
93        assert_eq!(x.as_f64(), 1_000_001.0f64);
94        assert_eq!(x.as_f64_lossy(), 1_000_001.0f64);
95        assert_eq!(x.as_seconds(), 1.000001f64);
96
97        assert_eq!(x.to_string(), "1000001us");
98
99        // Add
100        assert_eq!(
101            MicroSeconds::new(2) + MicroSeconds::new(3),
102            MicroSeconds::new(5)
103        );
104
105        // Sum
106        let x = [
107            MicroSeconds::new(1),
108            MicroSeconds::new(2),
109            MicroSeconds::new(3),
110        ];
111        let s: MicroSeconds = x.into_iter().sum();
112        assert_eq!(s, MicroSeconds::new(6));
113
114        // From Duration
115        let x = std::time::Duration::from_micros(12345);
116        let y: MicroSeconds = x.into();
117        assert_eq!(y, MicroSeconds::new(12345));
118    }
119
120    #[test]
121    fn test_microseconds_serde() {
122        let x: MicroSeconds = serde_json::from_str("15243").unwrap();
123        assert_eq!(x, MicroSeconds::new(15243));
124
125        let s = serde_json::to_string(&x).unwrap();
126        assert_eq!(s, "15243");
127    }
128}