#[macro_export]
macro_rules! binary_benchmark_attribute {
($name:ident) => {{
let mut binary_benchmark = $crate::BinaryBenchmark::new(stringify!($name));
binary_benchmark.config = $name::__get_config();
for internal_bench in $name::__BENCHES {
let mut bench = if let Some(id) = internal_bench.id_display {
$crate::Bench::new(id)
} else {
$crate::Bench::new(stringify!($name))
};
let mut bench = bench.command((internal_bench.func)());
if let Some(setup) = internal_bench.setup {
bench.setup(setup);
}
if let Some(teardown) = internal_bench.teardown {
bench.teardown(teardown);
}
if let Some(config) = internal_bench.config {
bench.config(config());
}
binary_benchmark.bench(bench);
}
binary_benchmark
}};
}
#[macro_export]
macro_rules! main {
( $( options = $( $options:literal ),+ $(,)*; )?
$( before = $before:ident $(, bench = $bench_before:literal )? ; )?
$( after = $after:ident $(, bench = $bench_after:literal )? ; )?
$( setup = $setup:ident $(, bench = $bench_setup:literal )? ; )?
$( teardown = $teardown:ident $(, bench = $bench_teardown:literal )? ; )?
$( sandbox = $sandbox:literal; )?
$( fixtures = $fixtures:literal $(, follow_symlinks = $follow_symlinks:literal )? ; )?
$( run = cmd = $cmd:expr
$(, envs = [ $( $envs:literal ),* $(,)* ] )?,
$( id = $id:literal, args = [ $( $args:literal ),* $(,)* ] ),+ $(,)*
);+ $(;)*
) => {
compile_error!(
"You are using a deprecated syntax of the main! macro to set up binary benchmarks. \
See the README (https://github.com/iai-callgrind/iai-callgrind) and \
docs (https://docs.rs/iai-callgrind/latest/iai_callgrind/) for further details."
);
pub fn main() {}
};
(
$( config = $config:expr; $(;)* )?
$( setup = $setup:expr ; $(;)* )?
$( teardown = $teardown:expr ; $(;)* )?
binary_benchmark_groups =
) => {
compile_error!("The binary_benchmark_groups argument needs at least one `name` of a `binary_benchmark_group!`");
};
(
$( config = $config:expr; $(;)* )?
$( setup = $setup:expr ; $(;)* )?
$( teardown = $teardown:expr ; $(;)* )?
binary_benchmark_groups = $( $group:ident ),+ $(,)*
) => {
fn __run() -> Result<(), $crate::__internal::error::Errors> {
let mut this_args = std::env::args();
let mut runner = $crate::__internal::Runner::new(
option_env!("IAI_CALLGRIND_RUNNER").or_else(||
option_env!("CARGO_BIN_EXE_iai-callgrind-runner")
),
&$crate::__internal::BenchmarkKind::BinaryBenchmark,
env!("CARGO_MANIFEST_DIR"),
env!("CARGO_PKG_NAME"),
file!(),
module_path!(),
this_args.next().unwrap(),
);
let mut config: Option<$crate::__internal::InternalBinaryBenchmarkConfig> = None;
$(
config = Some($config.into());
)?
let mut groups_builder = $crate::__internal::bin_bench::GroupsBuilder::new(
config, this_args.collect(), __run_setup(false), __run_teardown(false),
);
$(
let mut group = $crate::BinaryBenchmarkGroup::default();
$group::$group(&mut group);
groups_builder.add_group(
group,
stringify!($group).to_owned(),
&module_path!(),
$group::__IS_ATTRIBUTE,
$group::__get_config(),
$group::__run_setup(false),
$group::__run_teardown(false),
$group::__compare_by_id(),
$group::__BENCHES
);
)+
let groups = groups_builder.build()?;
let encoded = $crate::bincode::serialize(&groups).expect("Encoded benchmark");
runner.exec(encoded)
}
fn __run_setup(__run: bool) -> bool {
let mut __has_setup = false;
$(
__has_setup = true;
if __run {
$setup;
}
)?
__has_setup
}
fn __run_teardown(__run: bool) -> bool {
let mut __has_teardown = false;
$(
__has_teardown = true;
if __run {
$teardown;
}
)?
__has_teardown
}
fn main() {
let mut args_iter = std::env::args().skip(1);
if args_iter
.next()
.as_ref()
.map_or(false, |value| value == "--iai-run")
{
let mut current = args_iter.next().expect("Expecting a function type");
let next = args_iter.next();
match (current.as_str(), next) {
("setup", None) => {
__run_setup(true);
},
("teardown", None) => {
__run_teardown(true);
},
$(
(group @ stringify!($group), Some(next)) => {
let current = next;
let next = args_iter.next();
match (current.as_str(), next) {
("setup", None) => {
$group::__run_setup(true);
},
("teardown", None) => {
$group::__run_teardown(true);
}
(key @ ("setup" | "teardown"), Some(next)) => {
let group_index = next
.parse::<usize>()
.expect("The group index should be a number");
let bench_index = args_iter
.next()
.expect("The bench index should be present")
.parse::<usize>()
.expect("The bench index should be a number");
if key == "setup" {
$group::__run_bench_setup(group_index, bench_index);
} else {
$group::__run_bench_teardown(group_index, bench_index);
}
}
(name, _) => panic!("Invalid function '{}' in group '{}'", name, group)
}
}
)+
(name, _) => panic!("function '{}' not found in this scope", name)
}
} else {
if let Err(errors) = __run() {
eprintln!("{errors}");
std::process::exit(1);
}
};
}
};
(
$( config = $config:expr; $(;)* )?
$( setup = $setup:expr ; $(;)* )?
$( teardown = $teardown:expr ; $(;)* )?
library_benchmark_groups =
) => {
compile_error!("The library_benchmark_groups argument needs at least one `name` of a `library_benchmark_group!`");
};
(
$( config = $config:expr ; $(;)* )?
$( setup = $setup:expr ; $(;)* )?
$( teardown = $teardown:expr ; $(;)* )?
library_benchmark_groups = $( $group:ident ),+ $(,)*
) => {
#[inline(never)]
fn __run() {
let mut this_args = std::env::args();
let mut runner = $crate::__internal::Runner::new(
option_env!("IAI_CALLGRIND_RUNNER").or_else(||
option_env!("CARGO_BIN_EXE_iai-callgrind-runner")
),
&$crate::__internal::BenchmarkKind::LibraryBenchmark,
env!("CARGO_MANIFEST_DIR"),
env!("CARGO_PKG_NAME"),
file!(),
module_path!(),
this_args.next().unwrap(),
);
let mut config: Option<$crate::__internal::InternalLibraryBenchmarkConfig> = None;
$(
config = Some($config.into());
)?
let mut groups_builder = $crate::__internal::lib_bench::GroupsBuilder::new(
config, this_args.collect(), __run_setup(false), __run_teardown(false),
);
$(
groups_builder.add_group(
stringify!($group).to_owned(),
$group::__get_config(),
$group::__compare_by_id(),
$group::__run_setup(false),
$group::__run_teardown(false),
$group::__BENCHES
);
)+
let encoded = $crate::bincode::serialize(&groups_builder.build())
.expect("Encoded benchmark");
if let Err(errors) = runner.exec(encoded) {
eprintln!("{errors}");
std::process::exit(1);
}
}
#[inline(never)]
fn __run_setup(__run: bool) -> bool {
let mut __has_setup = false;
$(
__has_setup = true;
if __run {
$setup;
}
)?
__has_setup
}
#[inline(never)]
fn __run_teardown(__run: bool) -> bool {
let mut __has_teardown = false;
$(
__has_teardown = true;
if __run {
$teardown;
}
)?
__has_teardown
}
fn main() {
let mut args_iter = std::hint::black_box(std::env::args()).skip(1);
if args_iter
.next()
.as_ref()
.map_or(false, |value| value == "--iai-run")
{
let current = std::hint::black_box(args_iter.next().expect("Expecting a function type"));
let next = std::hint::black_box(args_iter.next());
match current.as_str() {
"setup" if next.is_none() => {
__run_setup(true);
},
"teardown" if next.is_none() => {
__run_teardown(true);
},
$(
stringify!($group) => {
match std::hint::black_box(
next
.expect("An argument `setup`, `teardown` or an index should be present")
.as_str()
) {
"setup" => {
$group::__run_setup(true);
},
"teardown" => {
$group::__run_teardown(true);
}
value => {
let group_index = std::hint::black_box(
value
.parse::<usize>()
.expect("Expecting a valid group index")
);
let bench_index = std::hint::black_box(
args_iter
.next()
.expect("A bench index should be present")
.parse::<usize>()
.expect("Expecting a valid bench index")
);
$group::__run(group_index, bench_index);
}
}
}
)+
name => panic!("function '{}' not found in this scope", name)
}
} else {
std::hint::black_box(__run());
};
}
};
(
callgrind_args = $( $args:literal ),* $(,)*; $(;)*
functions = $( $func_name:ident ),+ $(,)*
) => {
compile_error!(
"You are using a deprecated syntax of the main! macro to set up library benchmarks. \
See the README (https://github.com/iai-callgrind/iai-callgrind) and \
docs (https://docs.rs/iai-callgrind/latest/iai_callgrind/) for further details."
);
pub fn main() {}
};
( $( $func_name:ident ),+ $(,)* ) => {
compile_error!(
"You are using a deprecated syntax of the main! macro to set up library benchmarks. \
See the README (https://github.com/iai-callgrind/iai-callgrind) and \
docs (https://docs.rs/iai-callgrind/latest/iai_callgrind/) for further details."
);
pub fn main() {}
};
}
#[macro_export]
macro_rules! binary_benchmark_group {
(
name = $name:ident; $(;)*
$(before = $before:ident $(,bench = $bench_before:literal)? ; $(;)*)?
$(after = $after:ident $(,bench = $bench_after:literal)? ; $(;)*)?
$(setup = $setup:ident $(,bench = $bench_setup:literal)? ; $(;)*)?
$(teardown = $teardown:ident $(,bench = $bench_teardown:literal)? ; $(;)*)?
$( config = $config:expr ; $(;)* )?
benchmark = |$cmd:literal, $group:ident: &mut BinaryBenchmarkGroup| $body:expr
) => {
compile_error!(
"You are using a deprecated syntax of the binary_benchmark_group! macro to set up binary \
benchmarks. See the README (https://github.com/iai-callgrind/iai-callgrind), the \
CHANGELOG on the same page and docs (https://docs.rs/iai-callgrind/latest/iai_callgrind) \
for further details."
);
};
(
name = $name:ident; $(;)*
$( before = $before:ident $(,bench = $bench_before:literal)? ; $(;)* )?
$( after = $after:ident $(,bench = $bench_after:literal)? ; $(;)* )?
$( setup = $setup:ident $(,bench = $bench_setup:literal)? ; $(;)* )?
$( teardown = $teardown:ident $(,bench = $bench_teardown:literal )? ; $(;)* )?
$( config = $config:expr ; $(;)* )?
benchmark = |$group:ident: &mut BinaryBenchmarkGroup| $body:expr
) => {
compile_error!(
"You are using a deprecated syntax of the binary_benchmark_group! macro to set up binary \
benchmarks. See the README (https://github.com/iai-callgrind/iai-callgrind), the \
CHANGELOG on the same page and docs (https://docs.rs/iai-callgrind/latest/iai_callgrind) \
for further details."
);
};
(
$( config = $config:expr ; $(;)* )?
$( compare_by_id = $compare:literal ; $(;)* )?
$( setup = $setup:expr; $(;)* )?
$( teardown = $teardown:expr; $(;)* )?
benchmarks = $( $function:ident ),+ $(,)*
) => {
compile_error!(
"A binary_benchmark_group! needs a unique name. See the documentation of this macro for \
further details.\n\n\
hint = binary_benchmark_group!(name = some_ident; benchmarks = some_binary_benchmark);"
);
};
(
name = $name:ident; $(;)*
$( config = $config:expr; $(;)* )?
$( compare_by_id = $compare:literal; $(;)* )?
$( setup = $setup:expr; $(;)* )?
$( teardown = $teardown:expr; $(;)* )?
benchmarks =
) => {
compile_error!(
"A binary_benchmark_group! needs at least 1 benchmark function which is annotated with \
#[binary_benchmark] or you can use the low level syntax. See the documentation of this \
macro for further details.\n\n\
hint = binary_benchmark_group!(name = some_ident; benchmarks = some_binary_benchmark);"
);
};
(
name = $name:ident; $(;)*
$( config = $config:expr ; $(;)* )?
$( compare_by_id = $compare:literal ; $(;)* )?
$( setup = $setup:expr; $(;)* )?
$( teardown = $teardown:expr; $(;)* )?
) => {
compile_error!(
"A binary_benchmark_group! needs at least 1 benchmark function which is annotated with \
#[binary_benchmark] or you can use the low level syntax. See the documentation of this \
macro for further details.\n\n\
hint = binary_benchmark_group!(name = some_ident; benchmarks = some_binary_benchmark);"
);
};
(
name = $name:ident; $(;)*
$( config = $config:expr ; $(;)* )?
$( compare_by_id = $compare:literal ; $(;)* )?
$( setup = $setup:expr; $(;)* )?
$( teardown = $teardown:expr; $(;)* )?
benchmarks = $( $function:ident ),+ $(,)*
) => {
pub mod $name {
use super::*;
pub const __IS_ATTRIBUTE: bool = true;
pub const __BENCHES: &[&(
&'static str,
fn() -> Option<$crate::__internal::InternalBinaryBenchmarkConfig>,
&[$crate::__internal::InternalMacroBinBench]
)]= &[
$(
&(
stringify!($function),
super::$function::__get_config,
super::$function::__BENCHES
)
),+
];
pub fn __run_setup(__run: bool) -> bool {
let mut __has_setup = false;
$(
__has_setup = true;
if __run {
$setup;
}
)?
__has_setup
}
pub fn __run_teardown(__run: bool) -> bool {
let mut __has_teardown = false;
$(
__has_teardown = true;
if __run {
$teardown;
}
)?
__has_teardown
}
pub fn __compare_by_id() -> Option<bool> {
let mut comp = None;
$(
comp = Some($compare);
)?
comp
}
pub fn __get_config() -> Option<$crate::__internal::InternalBinaryBenchmarkConfig> {
let mut config = None;
$(
config = Some($config.into());
)?
config
}
pub fn __run_bench_setup(group_index: usize, bench_index: usize) {
if let Some(setup) = __BENCHES[group_index].2[bench_index].setup {
setup();
};
}
pub fn __run_bench_teardown(group_index: usize, bench_index: usize) {
if let Some(teardown) = __BENCHES[group_index].2[bench_index].teardown {
teardown();
};
}
pub fn $name(_: &mut $crate::BinaryBenchmarkGroup) {}
}
};
(
$( config = $config:expr; $(;)* )?
$( compare_by_id = $compare:literal ; $(;)* )?
$( setup = $setup:expr; $(;)* )?
$( teardown = $teardown:expr; $(;)* )?
benchmarks = |$group:ident: &mut BinaryBenchmarkGroup| $body:expr
) => {
compile_error!(
"A binary_benchmark_group! needs a unique name. See the documentation of this macro for \
further details.\n\n\
hint = binary_benchmark_group!(name = some_ident; benchmarks = |group: &mut BinaryBenchmarkGroup| ... );"
);
};
(
$( config = $config:expr; $(;)* )?
$( compare_by_id = $compare:literal ; $(;)* )?
$( setup = $setup:expr; $(;)* )?
$( teardown = $teardown:expr; $(;)* )?
benchmarks = |$group:ident| $body:expr
) => {
compile_error!(
"A binary_benchmark_group! needs a unique name. See the documentation of this macro for \
further details.\n\n\
hint = binary_benchmark_group!(name = some_ident; benchmarks = |group| ... );"
);
};
(
name = $name:ident; $(;)*
$( config = $config:expr; $(;)* )?
$( compare_by_id = $compare:literal ; $(;)* )?
$( setup = $setup:expr; $(;)* )?
$( teardown = $teardown:expr; $(;)* )?
benchmarks = |$group:ident|
) => {
compile_error!(
"This low level form of the binary_benchmark_group! needs you to use the \
`BinaryBenchmarkGroup` to setup benchmarks. See the documentation of this macro for \
further details.\n\n\
hint = binary_benchmark_group!(name = some_ident; benchmarks = |group| { \
group.binary_benchmark(/* BinaryBenchmark::new */); });"
);
};
(
name = $name:ident; $(;)*
$( config = $config:expr; $(;)* )?
$( compare_by_id = $compare:literal ; $(;)* )?
$( setup = $setup:expr; $(;)* )?
$( teardown = $teardown:expr; $(;)* )?
benchmarks = |$group:ident: &mut BinaryBenchmarkGroup|
) => {
compile_error!(
"This low level form of the binary_benchmark_group! needs you to use the \
`BinaryBenchmarkGroup` to setup benchmarks. See the documentation of this macro for \
further details.\n\n\
hint = binary_benchmark_group!(name = some_ident; benchmarks = |group: &mut \
BinaryBenchmarkGroup| { group.binary_benchmark(/* BinaryBenchmark::new */); });"
);
};
(
name = $name:ident; $(;)*
$( config = $config:expr; $(;)* )?
$( compare_by_id = $compare:literal ; $(;)* )?
$( setup = $setup:expr; $(;)* )?
$( teardown = $teardown:expr; $(;)* )?
benchmarks = |$group:ident: &mut BinaryBenchmarkGroup| $body:expr
) => {
pub mod $name {
use super::*;
pub const __IS_ATTRIBUTE: bool = false;
pub const __BENCHES: &[&(
&'static str,
fn() -> Option<$crate::__internal::InternalBinaryBenchmarkConfig>,
&[$crate::__internal::InternalMacroBinBench]
)]= &[];
pub fn __run_setup(__run: bool) -> bool {
let mut __has_setup = false;
$(
__has_setup = true;
if __run {
$setup;
}
)?
__has_setup
}
pub fn __run_teardown(__run: bool) -> bool {
let mut __has_teardown = false;
$(
__has_teardown = true;
if __run {
$teardown;
}
)?
__has_teardown
}
pub fn __get_config() -> Option<$crate::__internal::InternalBinaryBenchmarkConfig> {
let mut config = None;
$(
config = Some($config.into());
)?
config
}
pub fn __compare_by_id() -> Option<bool> {
let mut comp = None;
$(
comp = Some($compare);
)?
comp
}
pub fn __run_bench_setup(group_index: usize, bench_index: usize) {
let mut group = $crate::BinaryBenchmarkGroup::default();
$name(&mut group);
let bench = group
.binary_benchmarks
.iter()
.nth(group_index)
.expect("The group index for setup should be present");
if let Some(setup) = bench
.benches
.iter()
.flat_map(|b| b.commands.iter().map(|c| (b.setup, c)))
.nth(bench_index)
.map(|(setup, _)| setup)
.expect("The bench index for setup should be present") {
setup();
} else if let Some(setup) = bench.setup {
setup();
} else {
}
}
pub fn __run_bench_teardown(group_index: usize, bench_index: usize) {
let mut group = $crate::BinaryBenchmarkGroup::default();
$name(&mut group);
let bench = group
.binary_benchmarks
.iter()
.nth(group_index)
.expect("The group index for teardown should be present");
if let Some(teardown) = bench
.benches
.iter()
.flat_map(|b| b.commands.iter().map(|c| (b.teardown, c)))
.nth(bench_index)
.map(|(teardown, _)| teardown)
.expect("The bench index for teardown should be present") {
teardown();
} else if let Some(teardown) = bench.teardown {
teardown();
} else {
}
}
#[inline(never)]
pub fn $name($group: &mut $crate::BinaryBenchmarkGroup) {
$body;
}
}
};
(
name = $name:ident; $(;)*
$( config = $config:expr; $(;)* )?
$( compare_by_id = $compare:literal ; $(;)* )?
$( setup = $setup:expr; $(;)* )?
$( teardown = $teardown:expr; $(;)* )?
benchmarks = |$group:ident| $body:expr
) => {
binary_benchmark_group!(
name = $name;
$( config = $config; )?
$( compare_by_id = $compare; )?
$( setup = $setup; )?
$( teardown = $teardown; )?
benchmarks = |$group: &mut BinaryBenchmarkGroup| $body
);
};
}
#[macro_export]
macro_rules! library_benchmark_group {
(
$( config = $config:expr ; $(;)* )?
$( compare_by_id = $compare:literal ; $(;)* )?
$( setup = $setup:expr ; $(;)* )?
$( teardown = $teardown:expr ; $(;)* )?
benchmarks = $( $function:ident ),+
) => {
compile_error!("A library_benchmark_group! needs a name\n\nlibrary_benchmark_group!(name = some_ident; benchmarks = ...);");
};
(
name = $name:ident;
$( config = $config:expr ; $(;)* )?
$( compare_by_id = $compare:literal ; $(;)* )?
$( setup = $setup:expr ; $(;)* )?
$( teardown = $teardown:expr ; $(;)* )?
benchmarks =
) => {
compile_error!(
"A library_benchmark_group! needs at least 1 benchmark function \
annotated with #[library_benchmark]\n\n\
library_benchmark_group!(name = some_ident; benchmarks = some_library_benchmark);");
};
(
name = $name:ident; $(;)*
$( config = $config:expr ; $(;)* )?
$( compare_by_id = $compare:literal ; $(;)* )?
$( setup = $setup:expr ; $(;)* )?
$( teardown = $teardown:expr ; $(;)* )?
benchmarks = $( $function:ident ),+ $(,)*
) => {
pub mod $name {
use super::*;
pub const __BENCHES: &[&(
&'static str,
fn() -> Option<$crate::__internal::InternalLibraryBenchmarkConfig>,
&[$crate::__internal::InternalMacroLibBench]
)]= &[
$(
&(
stringify!($function),
super::$function::__get_config,
super::$function::__BENCHES
)
),+
];
#[inline(never)]
pub fn __get_config() -> Option<$crate::__internal::InternalLibraryBenchmarkConfig> {
let mut config: Option<$crate::__internal::InternalLibraryBenchmarkConfig> = None;
$(
config = Some($config.into());
)?
config
}
#[inline(never)]
pub fn __compare_by_id() -> Option<bool> {
let mut comp = None;
$(
comp = Some($compare);
)?
comp
}
#[inline(never)]
pub fn __run_setup(__run: bool) -> bool {
let mut __has_setup = false;
$(
__has_setup = true;
if __run {
$setup;
}
)?
__has_setup
}
#[inline(never)]
pub fn __run_teardown(__run: bool) -> bool {
let mut __has_teardown = false;
$(
__has_teardown = true;
if __run {
$teardown;
}
)?
__has_teardown
}
#[inline(never)]
pub fn __run(group_index: usize, bench_index: usize) {
(__BENCHES[group_index].2[bench_index].func)();
}
}
};
}