timelapse/
profiler.rs

1//! A simple profiler for measuring elapsed time in Rust.
2//!
3//! This module provides a `TimeLapse` struct and macros to start and end profiling.
4//! Macros `profile_start!` and `profile_end!` are used to simplify the profiling process.
5//!
6//! See the tesing examples at the end of this source file for usage.
7
8#![allow(unused)]
9use log::info;
10use std::time::{Duration, Instant};
11
12/// The `profile_start!` macro initializes a `TimeLapse` instance to start profiling.
13/// It takes an identifier as an argument, which will be instantiated and used to reference the profiler instance.
14///
15/// # Usage
16/// ```rust
17/// use std::time::Duration;
18/// use timelapse::{TimeLapse, profile_start, profile_end};
19///
20/// profile_start!(my_profiler);
21///
22/// std::thread::sleep(Duration::from_millis(100));
23/// assert!(my_profiler.elapsed().as_millis() >= 100);
24///
25/// profile_end!(my_profiler);
26/// ```
27#[macro_export]
28macro_rules! profile_start {
29    ($name:ident) => {
30        let $name = TimeLapse::new();
31    };
32}
33
34/// The `profile_end!` macro logs the elapsed time of the profiling instance created by `profile_start!`.
35/// These macros are useful for quick profiling without needing to manually create and manage `TimeLapse` instances.
36/// # Usage
37/// ```rust
38/// use std::time::Duration;
39/// use timelapse::{TimeLapse, profile_start, profile_end};
40///
41/// profile_start!(my_profiler);
42///
43/// std::thread::sleep(Duration::from_millis(100));
44/// assert!(my_profiler.elapsed().as_millis() >= 100);
45///
46/// profile_end!(my_profiler);
47/// ```
48#[macro_export]
49macro_rules! profile_end {
50    ($name:ident) => {
51        $name.log(stringify!($name));
52    };
53}
54
55/// The `TimeLapse` struct is used to measure elapsed time in Rust applications.
56/// It provides methods to start, reset, and log the elapsed time.
57/// It can be used to profile code execution and is useful for performance analysis.
58/// It implements the `Display` and `Debug` traits for easy formatting and logging.
59pub struct TimeLapse {
60    start_time: Instant,
61}
62
63impl TimeLapse {
64    /// Creates a new `TimeLapse` instance, starting the timer immediately.
65    pub fn new() -> Self {
66        TimeLapse {
67            start_time: Instant::now(),
68        }
69    }
70
71    /// Returns the elapsed time since the `TimeLapse` instance was created or reset.
72    pub fn elapsed(&self) -> Duration {
73        self.start_time.elapsed()
74    }
75
76    /// Resets the timer, starting a new measurement from the current time.
77    pub fn reset(&mut self) {
78        self.start_time = Instant::now();
79    }
80}
81
82/// Implements the `Display` trait for the `TimeLapse` struct.
83impl std::fmt::Display for TimeLapse {
84    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
85        write!(f, "Elapsed time: {:?}", self.elapsed())
86    }
87}
88
89/// Implements the `Debug` trait for the `TimeLapse` struct.
90impl std::fmt::Debug for TimeLapse {
91    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
92        write!(f, "TimeLapse {{ elapsed: {:?} }}", self.elapsed())
93    }
94}
95
96/// Implements the `Default` trait for the `TimeLapse` struct, allowing it to be created with default values.
97impl std::default::Default for TimeLapse {
98    fn default() -> Self {
99        Self::new()
100    }
101}
102
103impl TimeLapse {
104    /// Logs the elapsed time with a given name.
105    pub fn log(&self, name: &str) {
106        info!("TimeLapse {} - Elapsed time: {:?}", name, self.elapsed());
107    }
108}
109
110#[cfg(test)]
111mod tests {
112    use super::*;
113
114    #[test]
115    fn test_profiler() {
116        let profiler = TimeLapse::new();
117        std::thread::sleep(Duration::from_millis(100));
118        assert!(profiler.elapsed().as_millis() >= 100);
119        profiler.log("test");
120    }
121
122    #[test]
123    fn test_profiler_macros() {
124        profile_start!(the_profile);
125        std::thread::sleep(Duration::from_millis(100));
126        assert!(the_profile.elapsed().as_millis() >= 100);
127        profile_end!(the_profile);
128    }
129
130    #[test]
131    fn test_profiler_reset() {
132        let mut profiler = TimeLapse::new();
133        std::thread::sleep(Duration::from_millis(100));
134        profiler.reset();
135        assert!(profiler.elapsed().as_millis() < 50);
136    }
137}