Created
December 23, 2020 17:48
-
-
Save umcconnell/8054ef68d1870e0d23f617b67c9d5f89 to your computer and use it in GitHub Desktop.
Rust macro to profile a short snippet of code and return the evaluated result. Inspired by the `dbg!` macro.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/// Prints and returns the value of a given expression for quick and dirty code | |
/// profiling. | |
/// | |
/// Example usage: | |
/// | |
/// ```rust | |
/// let s = "hello world"; | |
/// let all_caps = profile!(s.repeat(2).to_uppercase()); | |
/// ^-- prints: [src/main.rs:2] execution time: 2μs | |
/// | |
/// println!("{}", all_caps); | |
/// ``` | |
/// | |
/// This macro works by measuring the execution time of a given expression using | |
/// `std::time::Instant` before returning it. The profiling information, | |
/// including the source file and line it originates from, is printed to | |
/// `stderr`. | |
/// | |
/// The macro takes ownership of the expression and returns the evaluated | |
/// output. | |
/// | |
/// Note that this macro is intended solely as a debugging or profiling tool. It | |
/// should therefore *not* be used in production builds and deploys. | |
/// | |
/// You can aso profile multiple expressions at once: | |
/// | |
/// ```rust | |
/// let name = "John"; | |
/// let (msg, length) = profile!( | |
/// { format!("Hello {}!", name) }, | |
/// { 7 + name.len() } | |
/// ); | |
/// | |
/// println!("{} (length: {})", msg, length); | |
/// ``` | |
/// | |
/// This prints (to stderr): | |
/// | |
/// ```text,ignore | |
/// [src/main.rs:3] execution time: 2μs | |
/// [src/main.rs:4] execution time: 0μs | |
/// ``` | |
/// | |
/// The `profile!(..)` macro moves the input: | |
/// | |
/// ```rust,compile_fail | |
/// struct NoCopy(i32); | |
/// | |
/// let n = NoCopy(42); | |
/// let _ = profile!(n); // <-- `n` is moved here | |
/// let _ = profile!(n); // <-- `n` is moved here again; error! | |
/// ``` | |
/// | |
/// Finally, a trailing comma in the macro call will be ignored: | |
/// | |
/// ```rust | |
/// let n = 42; | |
/// let _ = profile!(n,); // <-- Trailing comma is ignored | |
/// let _ = profile!(n); // <-- Same as above! | |
/// ``` | |
#[macro_export] | |
macro_rules! profile { | |
( $x:expr ) => {{ | |
use std::time::Instant; | |
use std::{eprintln, file, line}; | |
let timer = Instant::now(); | |
let _temp = $x; | |
eprintln!( | |
"[{}:{}] execution time: {}μs", | |
file!(), | |
line!(), | |
timer.elapsed().as_micros() | |
); | |
_temp | |
}}; | |
( $val:expr, ) => { $crate::profile!($val) }; | |
( $($val:expr),+ $(,)? ) => { | |
($($crate::profile!($val)),+,) | |
}; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment