ark_std/
perf_trace.rs
1#![allow(unused_imports)]
2pub use self::inner::*;
37
38#[macro_use]
39#[cfg(feature = "print-trace")]
40pub mod inner {
41 pub use colored::Colorize;
42
43 pub use std::{
45 format, println,
46 string::{String, ToString},
47 sync::atomic::{AtomicUsize, Ordering},
48 time::Instant,
49 };
50
51 pub static NUM_INDENT: AtomicUsize = AtomicUsize::new(0);
52 pub const PAD_CHAR: &str = "·";
53
54 pub struct TimerInfo {
55 pub msg: String,
56 pub time: Instant,
57 }
58
59 #[macro_export]
60 macro_rules! start_timer {
61 ($msg:expr) => {{
62 use $crate::perf_trace::inner::{
63 compute_indent, AtomicUsize, Colorize, Instant, Ordering, ToString, NUM_INDENT,
64 PAD_CHAR,
65 };
66
67 let msg = $msg();
68 let start_info = "Start:".yellow().bold();
69 let indent_amount = 2 * NUM_INDENT.fetch_add(0, Ordering::Relaxed);
70 let indent = compute_indent(indent_amount);
71
72 $crate::perf_trace::println!("{}{:8} {}", indent, start_info, msg);
73 NUM_INDENT.fetch_add(1, Ordering::Relaxed);
74 $crate::perf_trace::TimerInfo {
75 msg: msg.to_string(),
76 time: Instant::now(),
77 }
78 }};
79 }
80
81 #[macro_export]
82 macro_rules! end_timer {
83 ($time:expr) => {{
84 end_timer!($time, || "");
85 }};
86 ($time:expr, $msg:expr) => {{
87 use $crate::perf_trace::inner::{
88 compute_indent, format, AtomicUsize, Colorize, Instant, Ordering, ToString,
89 NUM_INDENT, PAD_CHAR,
90 };
91
92 let time = $time.time;
93 let final_time = time.elapsed();
94 let final_time = {
95 let secs = final_time.as_secs();
96 let millis = final_time.subsec_millis();
97 let micros = final_time.subsec_micros() % 1000;
98 let nanos = final_time.subsec_nanos() % 1000;
99 if secs != 0 {
100 format!("{}.{:03}s", secs, millis).bold()
101 } else if millis > 0 {
102 format!("{}.{:03}ms", millis, micros).bold()
103 } else if micros > 0 {
104 format!("{}.{:03}µs", micros, nanos).bold()
105 } else {
106 format!("{}ns", final_time.subsec_nanos()).bold()
107 }
108 };
109
110 let end_info = "End:".green().bold();
111 let message = format!("{} {}", $time.msg, $msg());
112
113 NUM_INDENT.fetch_sub(1, Ordering::Relaxed);
114 let indent_amount = 2 * NUM_INDENT.fetch_add(0, Ordering::Relaxed);
115 let indent = compute_indent(indent_amount);
116
117 $crate::perf_trace::println!(
120 "{}{:8} {:.<pad$}{}",
121 indent,
122 end_info,
123 message,
124 final_time,
125 pad = 75 - indent_amount
126 );
127 }};
128 }
129
130 #[macro_export]
131 macro_rules! add_to_trace {
132 ($title:expr, $msg:expr) => {{
133 use $crate::perf_trace::{
134 compute_indent, compute_indent_whitespace, format, AtomicUsize, Colorize, Instant,
135 Ordering, ToString, NUM_INDENT, PAD_CHAR,
136 };
137
138 let start_msg = "StartMsg".yellow().bold();
139 let end_msg = "EndMsg".green().bold();
140 let title = $title();
141 let start_msg = format!("{}: {}", start_msg, title);
142 let end_msg = format!("{}: {}", end_msg, title);
143
144 let start_indent_amount = 2 * NUM_INDENT.fetch_add(0, Ordering::Relaxed);
145 let start_indent = compute_indent(start_indent_amount);
146
147 let msg_indent_amount = 2 * NUM_INDENT.fetch_add(0, Ordering::Relaxed) + 2;
148 let msg_indent = compute_indent_whitespace(msg_indent_amount);
149 let mut final_message = "\n".to_string();
150 for line in $msg().lines() {
151 final_message += &format!("{}{}\n", msg_indent, line,);
152 }
153
154 $crate::perf_trace::println!("{}{}", start_indent, start_msg);
157 $crate::perf_trace::println!("{}{}", msg_indent, final_message,);
158 $crate::perf_trace::println!("{}{}", start_indent, end_msg);
159 }};
160 }
161
162 pub fn compute_indent_whitespace(indent_amount: usize) -> String {
163 let mut indent = String::new();
164 for _ in 0..indent_amount {
165 indent.push_str(" ");
166 }
167 indent
168 }
169
170 pub fn compute_indent(indent_amount: usize) -> String {
171 let mut indent = String::new();
172 for _ in 0..indent_amount {
173 indent.push_str(&PAD_CHAR.white());
174 }
175 indent
176 }
177}
178
179#[macro_use]
180#[cfg(not(feature = "print-trace"))]
181mod inner {
182 pub struct TimerInfo;
183
184 #[macro_export]
185 macro_rules! start_timer {
186 ($msg:expr) => {
187 $crate::perf_trace::TimerInfo
188 };
189 }
190 #[macro_export]
191 macro_rules! add_to_trace {
192 ($title:expr, $msg:expr) => {
193 let _ = $msg;
194 };
195 }
196
197 #[macro_export]
198 macro_rules! end_timer {
199 ($time:expr, $msg:expr) => {
200 let _ = $msg;
201 let _ = $time;
202 };
203 ($time:expr) => {
204 let _ = $time;
205 };
206 }
207}
208
209mod tests {
210 use super::*;
211
212 #[test]
213 fn print_start_end() {
214 let start = start_timer!(|| "Hello");
215 end_timer!(start);
216 }
217
218 #[test]
219 fn print_add() {
220 let start = start_timer!(|| "Hello");
221 add_to_trace!(|| "HelloMsg", || "Hello, I\nAm\nA\nMessage");
222 end_timer!(start);
223 }
224}