Skip to main content

gpui/
bench.rs

1/// Defines a Criterion benchmark group for benchmarks annotated with [`gpui::bench`].
2///
3/// This mirrors `criterion::criterion_group!`, but the group measures with the
4/// `gpui::BenchMeasurement` configured by `BENCH_MEASUREMENT` (see
5/// `BenchMeasurement::from_env`). By default Criterion analyzes wall time
6/// while retired instructions, cycles, IPC, context switches, and the other
7/// counters this machine supports are printed per iteration in the GPUI bench
8/// report. `BENCH_MEASUREMENT=instructions` makes Criterion analyze
9/// process-wide instructions instead, `foreground-instructions` the benchmark
10/// thread's alone, and `wall-time` disables all counters. A
11/// `config = ...` expression may set any other Criterion option; its
12/// measurement is replaced. To measure with something else, call
13/// `criterion::criterion_group!` directly with
14/// `config = criterion::Criterion::default().with_measurement(gpui::BenchMeasurement::new(...))`.
15///
16/// [`gpui::bench`]: crate::bench
17#[macro_export]
18macro_rules! bench_group {
19    (name = $name:ident; config = $config:expr; targets = $($target:path),+ $(,)?) => {
20        criterion::criterion_group! {
21            name = $name;
22            config = ($config).with_measurement($crate::BenchMeasurement::from_env_or_exit());
23            targets = $($target),+
24        }
25    };
26    ($name:ident, $($target:path),+ $(,)?) => {
27        $crate::bench_group! {
28            name = $name;
29            config = criterion::Criterion::default();
30            targets = $($target),+
31        }
32    };
33}
34
35/// Defines the entry point for GPUI Criterion benchmark groups.
36///
37/// This mirrors `criterion::criterion_main!` so GPUI benchmark files can keep the
38/// same shape as ordinary Criterion benchmarks. It also installs
39/// [`CountingAllocator`] as the binary's global allocator, so reports include
40/// heap allocations per iteration. It wraps the system allocator by default;
41/// `allocator = Path;` wraps another unit-struct allocator instead, e.g. to
42/// compare allocators, which pay the same small counting cost:
43///
44/// ```ignore
45/// gpui::bench_main!(allocator = mimalloc::MiMalloc; benches);
46/// ```
47///
48/// `allocator = none;` installs no global allocator, leaving Rust's default and
49/// dropping the allocation metrics from reports.
50#[macro_export]
51macro_rules! bench_main {
52    (allocator = none; $($groups:tt)*) => {
53        criterion::criterion_main!($($groups)*);
54    };
55    (allocator = $allocator:path; $($groups:tt)*) => {
56        #[global_allocator]
57        static GPUI_BENCH_ALLOCATOR: $crate::CountingAllocator<$allocator> =
58            $crate::CountingAllocator::new($allocator);
59
60        criterion::criterion_main!($($groups)*);
61    };
62    ($($groups:tt)*) => {
63        $crate::bench_main!(allocator = ::std::alloc::System; $($groups)*);
64    };
65}