Skip to content

Instantly share code, notes, and snippets.

@umcconnell
Created December 23, 2020 17:48
Show Gist options
  • Save umcconnell/8054ef68d1870e0d23f617b67c9d5f89 to your computer and use it in GitHub Desktop.
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.
/// 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