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}