Skip to main content

time_span/
lib.rs

1use std::time::Instant;
2
3/// 基于 RAII 的耗时统计器。
4///
5/// 离开作用域时自动触发 `Drop` 打印耗时。
6///
7/// # Examples
8///
9/// ```
10/// use time_span::TimeSpan;
11/// {
12///     let _guard = TimeSpan::new("heavy_work");
13///     // 耗时操作...
14/// } // _guard 离开作用域,自动打印耗时
15/// ```
16pub struct TimeSpan {
17    name: &'static str,
18    start: Instant,
19}
20
21impl TimeSpan {
22    /// 创建并启动一个新的计时器。
23    pub fn new(name: &'static str) -> Self {
24        Self {
25            name,
26            start: Instant::now(),
27        }
28    }
29}
30
31impl Drop for TimeSpan {
32    fn drop(&mut self) {
33        let elapsed = self.start.elapsed();
34        log::info!(
35            "[TIME] {} took {:.3} ms",
36            self.name,
37            elapsed.as_secs_f64() * 1000.0
38        );
39    }
40}
41
42/// 提供简化的宏封装,避免手动声明未使用变量。
43///
44/// # Examples
45///
46/// ```
47/// use time_span::time_span;
48/// fn process() {
49///     time_span!("process_func");
50///     // 耗时操作...
51/// }
52/// ```
53#[macro_export]
54macro_rules! time_span {
55    ($name:expr) => {
56        let _time_span_guard = $crate::TimeSpan::new($name);
57    };
58}
59
60/// 执行闭包并统计耗时,返回闭包的结果。
61///
62/// # Examples
63///
64/// ```
65/// use time_span::measure_time;
66/// let result = measure_time("calc_sum", || {
67///     1 + 1
68/// });
69/// ```
70pub fn measure_time<T, F>(name: &str, mut f: F) -> T
71where
72    F: FnMut() -> T,
73{
74    let start = Instant::now();
75    let result = f();
76    let elapsed = start.elapsed();
77    log::info!(
78        "[TIME] {} took {:.3} ms",
79        name,
80        elapsed.as_secs_f64() * 1000.0
81    );
82    result
83}
84
85#[cfg(test)]
86mod tests {
87    use super::*;
88    use std::thread;
89    use std::time::Duration;
90
91    #[test]
92    fn test_time_span_new() {
93        let _span = TimeSpan::new("test_span");
94    }
95
96    #[test]
97    fn test_time_span_drop() {
98        {
99            let _span = TimeSpan::new("drop_test");
100        }
101    }
102
103    #[test]
104    fn test_measure_time_basic() {
105        let result = measure_time("basic_test", || 42);
106        assert_eq!(result, 42);
107    }
108
109    #[test]
110    fn test_measure_time_with_sleep() {
111        let result = measure_time("sleep_test", || {
112            thread::sleep(Duration::from_millis(10));
113            "done"
114        });
115        assert_eq!(result, "done");
116    }
117
118    #[test]
119    fn test_measure_time_with_return() {
120        let result = measure_time("return_test", || {
121            let x = 10;
122            let y = 20;
123            x + y
124        });
125        assert_eq!(result, 30);
126    }
127
128    #[test]
129    fn test_macro_basic() {
130        time_span!("macro_test");
131    }
132
133    #[test]
134    fn test_macro_in_function() {
135        fn test_func() {
136            time_span!("func_test");
137            assert!(true);
138        }
139        test_func();
140    }
141
142    #[test]
143    fn test_multiple_spans() {
144        {
145            let _span1 = TimeSpan::new("span1");
146            {
147                let _span2 = TimeSpan::new("span2");
148            }
149        }
150    }
151
152    #[test]
153    fn test_nested_measure_time() {
154        let result = measure_time("outer", || measure_time("inner", || 100));
155        assert_eq!(result, 100);
156    }
157
158    #[test]
159    fn test_measure_time_with_mut() {
160        let mut count = 0;
161        let result = measure_time("mut_test", || {
162            count += 1;
163            count
164        });
165        assert_eq!(result, 1);
166        assert_eq!(count, 1);
167    }
168}