#![cfg_attr(not(feature = "std"), no_std)]
#![warn(missing_docs)]
#![warn(missing_debug_implementations)]
#![forbid(unsafe_code)]
#![deny(clippy::all)]
#![warn(clippy::pedantic)]
#![allow(clippy::module_name_repetitions)]
#![allow(clippy::must_use_candidate)]
#[cfg(feature = "collector")]
mod collector;
mod duration;
#[cfg(all(feature = "collector", feature = "metrics"))]
mod hist_backend;
#[cfg(all(feature = "collector", feature = "hdr"))]
mod hist_hdr;
#[cfg(feature = "collector")]
pub mod histogram;
mod measurement;
#[cfg(feature = "metrics")]
mod timer;
#[cfg(feature = "trace")]
mod trace;
#[cfg(feature = "metrics")]
mod watch;
#[cfg(feature = "collector")]
pub use collector::{Collector, Stats};
pub use duration::Duration;
pub use measurement::Measurement;
#[cfg(feature = "metrics")]
pub use timer::Timer;
#[cfg(feature = "metrics")]
pub use watch::{Watch, WatchBuilder, WatchStats};
#[doc(hidden)]
pub use crate as benchmark;
#[cfg(feature = "benchmark")]
use std::time::Instant;
#[cfg(feature = "benchmark")]
#[inline]
pub fn measure<T, F: FnOnce() -> T>(f: F) -> (T, Duration) {
let start = Instant::now();
let result = f();
let duration = Duration::from_nanos(start.elapsed().as_nanos());
(result, duration)
}
#[cfg(not(feature = "benchmark"))]
#[inline]
pub fn measure<T, F: FnOnce() -> T>(f: F) -> (T, Duration) {
(f(), Duration::ZERO)
}
#[cfg(all(feature = "benchmark", feature = "std"))]
#[inline]
pub fn measure_named<T, F: FnOnce() -> T>(name: &'static str, f: F) -> (T, Measurement) {
#[cfg(miri)]
let timestamp = 0;
#[cfg(not(miri))]
let timestamp = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.map_or(0, |d| d.as_nanos());
let start = Instant::now();
let result = f();
let duration = Duration::from_nanos(start.elapsed().as_nanos());
let measurement = Measurement {
name,
duration,
timestamp,
};
(result, measurement)
}
#[cfg(not(feature = "benchmark"))]
#[inline]
pub fn measure_named<T, F: FnOnce() -> T>(name: &'static str, f: F) -> (T, Measurement) {
let measurement = Measurement {
name,
duration: Duration::ZERO,
timestamp: 0,
};
(f(), measurement)
}
#[cfg(feature = "benchmark")]
#[macro_export]
macro_rules! time {
($expr:expr $(,)?) => {{
let __start = ::std::time::Instant::now();
let __out = { $expr };
let __dur = $crate::Duration::from_nanos(__start.elapsed().as_nanos());
(__out, __dur)
}};
}
#[cfg(not(feature = "benchmark"))]
#[macro_export]
macro_rules! time {
($expr:expr $(,)?) => {{
($expr, $crate::Duration::ZERO)
}};
}
#[cfg(feature = "benchmark")]
#[macro_export]
macro_rules! time_named {
($name:expr, $expr:expr $(,)?) => {{
let __name: &'static str = $name;
let __start = ::std::time::Instant::now();
let __out = { $expr };
let __dur = $crate::Duration::from_nanos(__start.elapsed().as_nanos());
#[cfg(miri)]
let __ts = 0;
#[cfg(not(miri))]
let __ts = ::std::time::SystemTime::now()
.duration_since(::std::time::UNIX_EPOCH)
.map_or(0, |d| d.as_nanos());
let __measurement = $crate::Measurement {
name: __name,
duration: __dur,
timestamp: __ts,
};
(__out, __measurement)
}};
}
#[cfg(not(feature = "benchmark"))]
#[macro_export]
macro_rules! time_named {
($name:expr, $expr:expr $(,)?) => {{
let measurement = $crate::Measurement {
name: $name,
duration: $crate::Duration::ZERO,
timestamp: 0,
};
($expr, measurement)
}};
}
#[cfg(feature = "metrics")]
#[macro_export]
macro_rules! stopwatch {
($watch:expr, $name:expr, { $($body:tt)* } $(,)?) => {{
let __timer = $crate::Timer::new($watch.clone(), $name);
{ $($body)* }
}};
}
#[cfg(not(all(feature = "metrics", feature = "std")))]
#[macro_export]
macro_rules! stopwatch {
($watch:expr, $name:expr, { $($body:tt)* } $(,)?) => {{
{ $($body)* }
}};
}
#[cfg(feature = "benchmark")]
#[macro_export]
macro_rules! benchmark_block {
({ $($body:tt)* } $(,)?) => {
$crate::benchmark_block!(10_000usize, { $($body)* })
};
($iters:expr, { $($body:tt)* } $(,)?) => {{
let __iters: usize = $iters;
let mut __samples: ::std::vec::Vec<$crate::Duration> = ::std::vec::Vec::with_capacity(__iters);
let mut __i = 0usize;
while __i < __iters {
let __start = ::std::time::Instant::now();
{ $($body)* }
let __dur = $crate::Duration::from_nanos(__start.elapsed().as_nanos());
__samples.push(__dur);
__i += 1;
}
__samples
}};
}
#[cfg(not(feature = "benchmark"))]
#[macro_export]
macro_rules! benchmark_block {
({ $($body:tt)* } $(,)?) => {{
{ $($body)* }
::std::vec::Vec::<$crate::Duration>::new()
}};
($iters:expr, { $($body:tt)* } $(,)?) => {{
let _ = $iters; { $($body)* }
::std::vec::Vec::<$crate::Duration>::new()
}};
}
#[cfg(feature = "benchmark")]
#[macro_export]
macro_rules! benchmark {
($name:expr, { $($body:tt)* } $(,)?) => {
$crate::benchmark!($name, 10_000usize, { $($body)* })
};
($name:expr, $iters:expr, { $($body:tt)* } $(,)?) => {{
let __name: &'static str = $name;
let __iters: usize = $iters;
let mut __measurements: ::std::vec::Vec<$crate::Measurement> = ::std::vec::Vec::with_capacity(__iters);
let mut __last = None;
let mut __i = 0usize;
while __i < __iters {
let __start = ::std::time::Instant::now();
let __out = { $($body)* };
let __dur = $crate::Duration::from_nanos(__start.elapsed().as_nanos());
#[cfg(miri)]
let __ts = 0;
#[cfg(not(miri))]
let __ts = ::std::time::SystemTime::now()
.duration_since(::std::time::UNIX_EPOCH)
.map_or(0, |d| d.as_nanos());
__measurements.push($crate::Measurement { name: __name, duration: __dur, timestamp: __ts });
__last = Some(__out);
__i += 1;
}
(__last, __measurements)
}};
($name:expr, $expr:expr $(,)?) => {
$crate::benchmark!($name, 10_000usize, { $expr })
};
($name:expr, $iters:expr, $expr:expr $(,)?) => {
$crate::benchmark!($name, $iters, { $expr })
};
}
#[cfg(not(feature = "benchmark"))]
#[macro_export]
macro_rules! benchmark {
($name:expr, { $($body:tt)* } $(,)?) => {{
let _ = $name;
let __out = { $($body)* };
(Some(__out), ::std::vec::Vec::<$crate::Measurement>::new())
}};
($name:expr, $iters:expr, { $($body:tt)* } $(,)?) => {{
let _ = ($name, $iters);
let __out = { $($body)* };
(Some(__out), ::std::vec::Vec::<$crate::Measurement>::new())
}};
($name:expr, $expr:expr $(,)?) => {{
let _ = $name;
let __out = $expr;
(Some(__out), ::std::vec::Vec::<$crate::Measurement>::new())
}};
($name:expr, $iters:expr, $expr:expr $(,)?) => {{
let _ = ($name, $iters);
let __out = $expr;
(Some(__out), ::std::vec::Vec::<$crate::Measurement>::new())
}};
}