codspeed_divan_compat_walltime/
lib.rs

1//! [bench_attr]: macro@bench
2//! [bench_attr_examples]: macro@bench#examples
3//! [bench_attr_threads]: macro@bench#threads
4#![doc = include_str!("../README.md")]
5#![warn(missing_docs)]
6#![allow(
7    unknown_lints,
8    unused_unsafe,
9    clippy::needless_doctest_main,
10    clippy::needless_lifetimes,
11    clippy::new_without_default,
12    clippy::type_complexity,
13    clippy::missing_transmute_annotations
14)]
15
16// Used by generated code. Not public API and thus not subject to SemVer.
17#[doc(hidden)]
18#[path = "private.rs"]
19pub mod __private;
20
21mod alloc;
22mod bench;
23mod cli;
24mod compile_fail;
25mod config;
26mod divan;
27mod entry;
28mod stats;
29mod thread_pool;
30mod time;
31mod tree_painter;
32mod util;
33
34pub mod counter;
35
36/// Prevents compiler optimizations on a value.
37///
38/// `black_box` should only be used on [inputs](#benchmark-inputs) and
39/// [outputs](#benchmark-outputs) of benchmarks. Newcomers to benchmarking may
40/// be tempted to also use `black_box` within the implementation, but doing so
41/// will overly pessimize the measured code without any benefit.
42///
43/// ## Benchmark Inputs
44///
45/// When benchmarking, it's good practice to ensure measurements are accurate by
46/// preventing the compiler from optimizing based on assumptions about benchmark
47/// inputs.
48///
49/// The compiler can optimize code for indices it knows about, such as by
50/// removing bounds checks or unrolling loops. If real-world use of your code
51/// would not know indices up front, consider preventing optimizations on them
52/// in benchmarks:
53///
54/// ```
55/// use divan::black_box;
56///
57/// const INDEX: usize = // ...
58/// # 0;
59/// const SLICE: &[u8] = // ...
60/// # &[];
61///
62/// #[divan::bench]
63/// fn bench() {
64///     # fn work<T>(_: T) {}
65///     work(&SLICE[black_box(INDEX)..]);
66/// }
67/// ```
68///
69/// The compiler may also optimize for the data itself, which can also be
70/// avoided with `black_box`:
71///
72/// ```
73/// # use divan::black_box;
74/// # const INDEX: usize = 0;
75/// # const SLICE: &[u8] = &[];
76/// #[divan::bench]
77/// fn bench() {
78///     # fn work<T>(_: T) {}
79///     work(black_box(&SLICE[black_box(INDEX)..]));
80/// }
81/// ```
82///
83/// ## Benchmark Outputs
84///
85/// When benchmarking, it's best to ensure that all of the code is actually
86/// being run. If the compiler knows an output is unused, it may remove the code
87/// that generated the output. This optimization can make benchmarks appear much
88/// faster than they really are.
89///
90/// At the end of a benchmark, we can force the compiler to treat outputs as if
91/// they were actually used:
92///
93/// ```
94/// # use divan::black_box;
95/// #[divan::bench]
96/// fn bench() {
97///     # let value = 1;
98///     black_box(value.to_string());
99/// }
100/// ```
101///
102/// To make the code clearer to readers that the output is discarded, this code
103/// could instead call [`black_box_drop`].
104///
105/// Alternatively, the output can be returned from the benchmark:
106///
107/// ```
108/// #[divan::bench]
109/// fn bench() -> String {
110///     # let value = 1;
111///     value.to_string()
112/// }
113/// ```
114///
115/// Returning the output will `black_box` it and also avoid measuring the time
116/// to [drop](Drop) the output, which in this case is the time to deallocate a
117/// [`String`]. Read more about this in the [`#[divan::bench]`
118/// docs](macro@bench#drop).
119///
120/// ---
121///
122/// <h1>Standard Library Documentation</h1>
123///
124#[doc(inline)]
125pub use std::hint::black_box;
126
127#[doc(inline)]
128pub use crate::{alloc::AllocProfiler, bench::Bencher, divan::Divan};
129
130/// Runs all registered benchmarks.
131///
132/// # Examples
133///
134/// ```
135/// #[divan::bench]
136/// fn add() -> i32 {
137///     // ...
138///     # 0
139/// }
140///
141/// fn main() {
142///     // Run `add` benchmark:
143///     divan::main();
144/// }
145/// ```
146///
147/// See [`#[divan::bench]`](macro@bench) for more examples.
148pub fn main() {
149    Divan::from_args().main();
150}
151
152/// [`black_box`] + [`drop`] convenience function.
153///
154/// # Examples
155///
156/// This is useful when benchmarking a lazy [`Iterator`] to completion with
157/// [`for_each`](Iterator::for_each):
158///
159/// ```
160/// #[divan::bench]
161/// fn parse_iter() {
162///     let input: &str = // ...
163///     # "";
164///
165///     # struct Parser;
166///     # impl Parser {
167///     #   fn new(_: &str) -> Parser { Parser }
168///     #   fn for_each(self, _: fn(&'static str)) {}
169///     # }
170///     Parser::new(input)
171///         .for_each(divan::black_box_drop);
172/// }
173/// ```
174#[inline]
175pub fn black_box_drop<T>(dummy: T) {
176    _ = black_box(dummy);
177}
178
179/// Registers a benchmarking function.
180///
181/// # Examples
182///
183/// The quickest way to get started is to benchmark the function as-is:
184///
185/// ```
186/// use divan::black_box;
187///
188/// #[divan::bench]
189/// fn add() -> i32 {
190///     black_box(1) + black_box(42)
191/// }
192///
193/// fn main() {
194///     // Run `add` benchmark:
195///     divan::main();
196/// }
197/// ```
198///
199/// If benchmarks need to setup context before running, they can take a
200/// [`Bencher`] and use [`Bencher::bench`]:
201///
202/// ```
203/// use divan::{Bencher, black_box};
204///
205/// #[divan::bench]
206/// fn copy_from_slice(bencher: Bencher) {
207///     let src = (0..100).collect::<Vec<i32>>();
208///     let mut dst = vec![0; src.len()];
209///
210///     bencher.bench_local(move || {
211///         black_box(&mut dst).copy_from_slice(black_box(&src));
212///     });
213/// }
214/// ```
215///
216/// Applying this attribute multiple times to the same item will cause a compile
217/// error:
218///
219/// ```compile_fail
220/// #[divan::bench]
221/// #[divan::bench]
222/// fn bench() {
223///     // ...
224/// }
225/// ```
226///
227/// # Drop
228///
229/// When a benchmarked function returns a value, it will not be [dropped][Drop]
230/// until after the current sample loop is finished. This allows for more
231/// precise timing measurements.
232///
233/// Note that there is an inherent memory cost to defer drop, including
234/// allocations inside not-yet-dropped values. Also, if the benchmark
235/// [panics](macro@std::panic), the values will never be dropped.
236///
237/// The following example benchmarks will only measure [`String`] construction
238/// time, but not deallocation time:
239///
240/// ```
241/// use divan::{Bencher, black_box};
242///
243/// #[divan::bench]
244/// fn freestanding() -> String {
245///     black_box("hello").to_uppercase()
246/// }
247///
248/// #[divan::bench]
249/// fn contextual(bencher: Bencher) {
250///     // Setup:
251///     let s: String = // ...
252///     # String::new();
253///
254///     bencher.bench(|| -> String {
255///         black_box(&s).to_lowercase()
256///     });
257/// }
258/// ```
259///
260/// If the returned value *does not* need to be dropped, there is no memory
261/// cost. Because of this, the following example benchmarks are equivalent:
262///
263/// ```
264/// #[divan::bench]
265/// fn with_return() -> i32 {
266///     let n: i32 = // ...
267///     # 0;
268///     n
269/// }
270///
271/// #[divan::bench]
272/// fn without_return() {
273///     let n: i32 = // ...
274///     # 0;
275///     divan::black_box(n);
276/// }
277/// ```
278///
279/// # Options
280///
281/// - [`name`]
282/// - [`crate`]
283/// - [`args`]
284/// - [`consts`]
285/// - [`types`]
286/// - [`sample_count`]
287/// - [`sample_size`]
288/// - [`threads`]
289/// - [`counters`]
290///     - [`bytes_count`]
291///     - [`chars_count`]
292///     - [`items_count`]
293/// - [`min_time`]
294/// - [`max_time`]
295/// - [`skip_ext_time`]
296/// - [`ignore`]
297///
298/// ## `name`
299/// [`name`]: #name
300///
301/// By default, the benchmark uses the function's name. It can be overridden via
302/// the [`name`] option:
303///
304/// ```
305/// #[divan::bench(name = "my_add")]
306/// fn add() -> i32 {
307///     // Will appear as "crate_name::my_add".
308///     # 0
309/// }
310/// ```
311///
312/// ## `crate`
313/// [`crate`]: #crate
314///
315/// The path to the specific `divan` crate instance used by this macro's
316/// generated code can be specified via the [`crate`] option. This is applicable
317/// when using `divan` via a macro from your own crate.
318///
319/// ```
320/// extern crate divan as sofa;
321///
322/// #[::sofa::bench(crate = ::sofa)]
323/// fn add() -> i32 {
324///     // ...
325///     # 0
326/// }
327/// ```
328///
329/// ## `args`
330/// [`args`]: #args
331///
332/// Function arguments can be provided to benchmark the function over multiple
333/// cases. This is used for comparing across parameters like collection lengths
334/// and [`enum`](https://doc.rust-lang.org/std/keyword.enum.html) variants. If
335/// you are not comparing cases and just need to pass a value into the
336/// benchmark, instead consider passing local values into the [`Bencher::bench`]
337/// closure or use [`Bencher::with_inputs`] for many distinct values.
338///
339/// The following example benchmarks converting a [`Range`](std::ops::Range) to
340/// [`Vec`] over different lengths:
341///
342/// ```
343/// #[divan::bench(args = [1000, LEN, len()])]
344/// fn init_vec(len: usize) -> Vec<usize> {
345///     (0..len).collect()
346/// }
347///
348/// const LEN: usize = // ...
349/// # 0;
350///
351/// fn len() -> usize {
352///     // ...
353///     # 0
354/// }
355/// ```
356///
357/// The list of arguments can be shared across multiple benchmarks through an
358/// external [`Iterator`]:
359///
360/// ```
361/// const LENS: &[usize] = // ...
362/// # &[];
363///
364/// #[divan::bench(args = LENS)]
365/// fn bench_vec1(len: usize) -> Vec<usize> {
366///     // ...
367///     # vec![]
368/// }
369///
370/// #[divan::bench(args = LENS)]
371/// fn bench_vec2(len: usize) -> Vec<usize> {
372///     // ...
373///     # vec![]
374/// }
375/// ```
376///
377/// Unlike the [`consts`] option, any argument type is supported if it
378/// implements [`Any`], [`Copy`], [`Send`], [`Sync`], and [`ToString`] (or
379/// [`Debug`](std::fmt::Debug)):
380///
381/// ```
382/// #[derive(Clone, Copy, Debug)]
383/// enum Arg {
384///     A, B
385/// }
386///
387/// #[divan::bench(args = [Arg::A, Arg::B])]
388/// fn bench_args(arg: Arg) {
389///     // ...
390/// }
391/// ```
392///
393/// The argument type does not need to implement [`Copy`] if it is used through
394/// a reference:
395///
396/// ```
397/// #[derive(Debug)]
398/// enum Arg {
399///     A, B
400/// }
401///
402/// #[divan::bench(args = [Arg::A, Arg::B])]
403/// fn bench_args(arg: &Arg) {
404///     // ...
405/// }
406/// ```
407///
408/// For convenience, common string types are coerced to [`&str`](primitive@str):
409///
410/// ```
411/// fn strings() -> impl Iterator<Item = String> {
412///     // ...
413///     # [].into_iter()
414/// }
415///
416/// #[divan::bench(args = strings())]
417/// fn bench_strings(s: &str) {
418///     // ...
419/// }
420/// ```
421///
422/// Arguments can also be used with [`Bencher`]. This allows for generating
423/// inputs based on [`args`] values or providing throughput information via
424/// [`Counter`s](crate::counter::Counter):
425///
426/// ```
427/// # fn new_value<T>(v: T) -> T { v }
428/// # fn do_work<T>(_: T) {}
429/// use divan::Bencher;
430///
431/// #[divan::bench(args = [1, 2, 3])]
432/// fn bench(bencher: Bencher, len: usize) {
433///     let value = new_value(len);
434///
435///     bencher
436///         .counter(len)
437///         .bench(|| {
438///             do_work(value);
439///         });
440/// }
441/// ```
442///
443/// ## `consts`
444/// [`consts`]: #consts
445///
446/// Divan supports benchmarking functions with [`const`
447/// generics](https://doc.rust-lang.org/reference/items/generics.html#const-generics)
448/// via the [`consts`] option.
449///
450/// The following example benchmarks initialization of [`[i32; N]`](prim@array)
451/// for values of `N` provided by a [literal](https://doc.rust-lang.org/reference/expressions/literal-expr.html),
452/// [`const` item](https://doc.rust-lang.org/reference/items/constant-items.html),
453/// and [`const fn`](https://doc.rust-lang.org/reference/const_eval.html#const-functions):
454///
455/// ```
456/// #[divan::bench(consts = [1000, LEN, len()])]
457/// fn init_array<const N: usize>() -> [i32; N] {
458///     let mut result = [0; N];
459///
460///     for i in 0..N {
461///         result[i] = divan::black_box(i as i32);
462///     }
463///
464///     result
465/// }
466///
467/// const LEN: usize = // ...
468/// # 0;
469///
470/// const fn len() -> usize {
471///     // ...
472///     # 0
473/// }
474/// ```
475///
476/// The list of constants can be shared across multiple benchmarks through an
477/// external [array](prim@array) or [slice](prim@slice):
478///
479/// ```
480/// const SIZES: &[usize] = &[1, 2, 5, 10];
481///
482/// #[divan::bench(consts = SIZES)]
483/// fn bench_array1<const N: usize>() -> [i32; N] {
484///     // ...
485///     # [0; N]
486/// }
487///
488/// #[divan::bench(consts = SIZES)]
489/// fn bench_array2<const N: usize>() -> [i32; N] {
490///     // ...
491///     # [0; N]
492/// }
493/// ```
494///
495/// External constants are limited to lengths 1 through 20, because of
496/// implementation details. This limit does not apply if the list is provided
497/// directly like in the first example.
498///
499/// ```compile_fail
500/// const SIZES: [usize; 21] = [
501///     // ...
502///     # 0; 21
503/// ];
504///
505/// #[divan::bench(consts = SIZES)]
506/// fn bench_array<const N: usize>() -> [i32; N] {
507///     // ...
508///     # [0; N]
509/// }
510/// ```
511///
512/// ## `types`
513/// [`types`]: #types
514///
515/// Divan supports benchmarking generic functions over a list of types via the
516/// [`types`] option.
517///
518/// The following example benchmarks the [`From<&str>`](From) implementations
519/// for [`&str`](prim@str) and [`String`]:
520///
521/// ```
522/// #[divan::bench(types = [&str, String])]
523/// fn from_str<'a, T>() -> T
524/// where
525///     T: From<&'a str>,
526/// {
527///     divan::black_box("hello world").into()
528/// }
529/// ```
530///
531/// The [`types`] and [`args`] options can be combined to benchmark _T_ × _A_
532/// scenarios. The following example benchmarks the [`FromIterator`]
533/// implementations for [`Vec`], [`BTreeSet`], and [`HashSet`]:
534///
535/// ```
536/// use std::collections::{BTreeSet, HashSet};
537///
538/// #[divan::bench(
539///     types = [Vec<i32>, BTreeSet<i32>, HashSet<i32>],
540///     args = [0, 2, 4, 16, 256, 4096],
541/// )]
542/// fn from_range<T>(n: i32) -> T
543/// where
544///     T: FromIterator<i32>,
545/// {
546///     (0..n).collect()
547/// }
548/// ```
549///
550/// [`BTreeSet`]: std::collections::BTreeSet
551/// [`HashSet`]: std::collections::HashSet
552///
553/// ## `sample_count`
554/// [`sample_count`]: #sample_count
555///
556/// The number of statistical sample recordings can be set to a predetermined
557/// [`u32`] value via the [`sample_count`] option. This may be overridden at
558/// runtime using either the `DIVAN_SAMPLE_COUNT` environment variable or
559/// `--sample-count` CLI argument.
560///
561/// ```
562/// #[divan::bench(sample_count = 1000)]
563/// fn add() -> i32 {
564///     // ...
565///     # 0
566/// }
567/// ```
568///
569/// If the [`threads`] option is enabled, sample count becomes a multiple of the
570/// number of threads. This is because each thread operates over the same sample
571/// size to ensure there are always N competing threads doing the same amount of
572/// work.
573///
574/// ## `sample_size`
575/// [`sample_size`]: #sample_size
576///
577/// The number iterations within each statistics sample can be set to a
578/// predetermined [`u32`] value via the [`sample_size`] option. This may be
579/// overridden at runtime using either the `DIVAN_SAMPLE_SIZE` environment
580/// variable or `--sample-size` CLI argument.
581///
582/// ```
583/// #[divan::bench(sample_size = 1000)]
584/// fn add() -> i32 {
585///     // ...
586///     # 0
587/// }
588/// ```
589///
590/// ## `threads`
591/// [`threads`]: #threads
592///
593/// Benchmarked functions can be run across multiple threads via the [`threads`]
594/// option. This enables you to measure contention on [atomics and
595/// locks][std::sync]. The default thread count is the [available parallelism].
596///
597/// ```
598/// use std::sync::Arc;
599///
600/// #[divan::bench(threads)]
601/// fn arc_clone(bencher: divan::Bencher) {
602///     let arc = Arc::new(42);
603///
604///     bencher.bench(|| arc.clone());
605/// }
606/// ```
607///
608/// The [`threads`] option can be set to any of:
609/// - [`bool`] for [available parallelism] (true) or no parallelism.
610/// - [`usize`] for a specific number of threads. 0 means use [available
611///   parallelism] and 1 means no parallelism.
612/// - [`IntoIterator`] over [`usize`] for multiple thread counts, such as:
613///     - [`Range<usize>`](std::ops::Range)
614///     - [`[usize; N]`](prim@array)
615///     - [`&[usize]`](prim@slice)
616///
617/// ```
618/// #[divan::bench(threads = false)]
619/// fn single() {
620///     // ...
621/// }
622///
623/// #[divan::bench(threads = 10)]
624/// fn specific() {
625///     // ...
626/// }
627///
628/// #[divan::bench(threads = 0..=8)]
629/// fn range() {
630///     // Note: Includes 0 for available parallelism.
631/// }
632///
633/// #[divan::bench(threads = [0, 1, 4, 8, 16])]
634/// fn selection() {
635///     // ...
636/// }
637/// ```
638///
639/// ## `counters`
640/// [`counters`]: #counters
641///
642/// The [`Counter`s](crate::counter::Counter) of each iteration can be set via
643/// the [`counters`] option. The following example emits info for the number of
644/// bytes and number of ints processed when benchmarking [slice sorting](slice::sort):
645///
646/// ```
647/// use divan::{Bencher, counter::{BytesCount, ItemsCount}};
648///
649/// const INTS: &[i32] = &[
650///     // ...
651/// ];
652///
653/// #[divan::bench(counters = [
654///     BytesCount::of_slice(INTS),
655///     ItemsCount::new(INTS.len()),
656/// ])]
657/// fn sort(bencher: Bencher) {
658///     bencher
659///         .with_inputs(|| INTS.to_vec())
660///         .bench_refs(|ints| ints.sort());
661/// }
662/// ```
663///
664/// For convenience, singular `counter` allows a single
665/// [`Counter`](crate::counter::Counter) to be set. The following example emits
666/// info for the number of bytes processed when benchmarking
667/// [`char`-counting](std::str::Chars::count):
668///
669/// ```
670/// use divan::counter::BytesCount;
671///
672/// const STR: &str = "...";
673///
674/// #[divan::bench(counter = BytesCount::of_str(STR))]
675/// fn char_count() -> usize {
676///     divan::black_box(STR).chars().count()
677/// }
678/// ```
679///
680/// See:
681/// - [`#[divan::bench_group(counters = ...)]`](macro@bench_group#counters)
682/// - [`Bencher::counter`]
683/// - [`Bencher::input_counter`]
684///
685/// ### `bytes_count`
686/// [`bytes_count`]: #bytes_count
687///
688/// Convenience shorthand for
689/// <code>[counter](#counters) = [BytesCount](counter::BytesCount)::from(n)</code>.
690///
691/// ### `chars_count`
692/// [`chars_count`]: #chars_count
693///
694/// Convenience shorthand for
695/// <code>[counter](#counters) = [CharsCount](counter::CharsCount)::from(n)</code>.
696///
697/// ### `items_count`
698/// [`items_count`]: #items_count
699///
700/// Convenience shorthand for
701/// <code>[counter](#counters) = [ItemsCount](counter::ItemsCount)::from(n)</code>.
702///
703/// ## `min_time`
704/// [`min_time`]: #min_time
705///
706/// The minimum time spent benchmarking each function can be set to a
707/// predetermined [`Duration`] via the [`min_time`] option. This may be
708/// overridden at runtime using either the `DIVAN_MIN_TIME` environment variable
709/// or `--min-time` CLI argument.
710///
711/// Unless [`skip_ext_time`] is set, this includes time external to the
712/// benchmarked function, such as time spent generating inputs and running
713/// [`Drop`].
714///
715/// ```
716/// use std::time::Duration;
717///
718/// #[divan::bench(min_time = Duration::from_secs(3))]
719/// fn add() -> i32 {
720///     // ...
721///     # 0
722/// }
723/// ```
724///
725/// For convenience, [`min_time`] can also be set with seconds as [`u64`] or
726/// [`f64`]. Invalid values will cause a panic at runtime.
727///
728/// ```
729/// #[divan::bench(min_time = 2)]
730/// fn int_secs() -> i32 {
731///     // ...
732///     # 0
733/// }
734///
735/// #[divan::bench(min_time = 1.5)]
736/// fn float_secs() -> i32 {
737///     // ...
738///     # 0
739/// }
740/// ```
741///
742/// ## `max_time`
743/// [`max_time`]: #max_time
744///
745/// The maximum time spent benchmarking each function can be set to a
746/// predetermined [`Duration`] via the [`max_time`] option. This may be
747/// overridden at runtime using either the `DIVAN_MAX_TIME` environment variable
748/// or `--max-time` CLI argument.
749///
750/// Unless [`skip_ext_time`] is set, this includes time external to the
751/// benchmarked function, such as time spent generating inputs and running
752/// [`Drop`].
753///
754/// If `min_time > max_time`, then [`max_time`] has priority and [`min_time`]
755/// will not be reached.
756///
757/// ```
758/// use std::time::Duration;
759///
760/// #[divan::bench(max_time = Duration::from_secs(5))]
761/// fn add() -> i32 {
762///     // ...
763///     # 0
764/// }
765/// ```
766///
767/// For convenience, like [`min_time`], [`max_time`] can also be set with
768/// seconds as [`u64`] or [`f64`]. Invalid values will cause a panic at runtime.
769///
770/// ```
771/// #[divan::bench(max_time = 8)]
772/// fn int_secs() -> i32 {
773///     // ...
774///     # 0
775/// }
776///
777/// #[divan::bench(max_time = 9.5)]
778/// fn float_secs() -> i32 {
779///     // ...
780///     # 0
781/// }
782/// ```
783///
784/// ## `skip_ext_time`
785/// [`skip_ext_time`]: #skip_ext_time
786///
787/// By default, [`min_time`] and [`max_time`] include time external to the
788/// benchmarked function, such as time spent generating inputs and running
789/// [`Drop`]. Enabling the [`skip_ext_time`] option will instead make those
790/// options only consider time spent within the benchmarked function. This may
791/// be overridden at runtime using either the `DIVAN_SKIP_EXT_TIME` environment
792/// variable or `--skip-ext-time` CLI argument.
793///
794/// In the following example, [`max_time`] only considers time spent running
795/// `measured_function`:
796///
797/// ```
798/// # fn generate_input() {}
799/// # fn measured_function(_: ()) {}
800/// #[divan::bench(max_time = 5, skip_ext_time)]
801/// fn bench(bencher: divan::Bencher) {
802///     bencher
803///         .with_inputs(|| generate_input())
804///         .bench_values(|input| measured_function(input));
805/// }
806/// ```
807///
808/// This option can be set to an explicit [`bool`] value to override parent
809/// values:
810///
811/// ```
812/// #[divan::bench(max_time = 5, skip_ext_time = false)]
813/// fn bench(bencher: divan::Bencher) {
814///     // ...
815/// }
816/// ```
817///
818/// ## `ignore`
819/// [`ignore`]: #ignore
820///
821/// Like [`#[test]`](https://doc.rust-lang.org/reference/attributes/testing.html#the-test-attribute),
822/// `#[divan::bench]` functions can use [`#[ignore]`](https://doc.rust-lang.org/reference/attributes/testing.html#the-ignore-attribute):
823///
824/// ```
825/// #[divan::bench]
826/// #[ignore]
827/// fn todo() {
828///     unimplemented!();
829/// }
830/// # divan::main();
831/// ```
832///
833/// This option can also instead be set within the `#[divan::bench]` attribute:
834///
835/// ```
836/// #[divan::bench(ignore)]
837/// fn todo() {
838///     unimplemented!();
839/// }
840/// # divan::main();
841/// ```
842///
843/// Like [`skip_ext_time`], this option can be set to an explicit [`bool`] value
844/// to override parent values:
845///
846/// ```
847/// #[divan::bench(ignore = false)]
848/// fn bench() {
849///     // ...
850/// }
851/// ```
852///
853/// This can be used to ignore benchmarks based on a runtime condition. The
854/// following example benchmark will be ignored if an [environment
855/// variable](std::env::var) is not set to "true":
856///
857/// ```
858/// #[divan::bench(
859///     ignore = std::env::var("BENCH_EXPENSIVE").as_deref() != Ok("true")
860/// )]
861/// fn expensive_bench() {
862///     // ...
863/// }
864/// ```
865///
866/// [`Any`]: std::any::Any
867/// [`Duration`]: std::time::Duration
868/// [available parallelism]: std::thread::available_parallelism
869pub use divan_macros::bench;
870
871/// Registers a benchmarking group.
872///
873/// # Examples
874///
875/// This is used for setting [options] shared across
876/// [`#[divan::bench]`](macro@bench) functions in the same module:
877///
878/// ```
879/// #[divan::bench_group(
880///     sample_count = 100,
881///     sample_size = 500,
882/// )]
883/// mod math {
884///     use divan::black_box;
885///
886///     #[divan::bench]
887///     fn add() -> i32 {
888///         black_box(1) + black_box(42)
889///     }
890///
891///     #[divan::bench]
892///     fn div() -> i32 {
893///         black_box(1) / black_box(42)
894///     }
895/// }
896///
897/// fn main() {
898///     // Run `math::add` and `math::div` benchmarks:
899///     divan::main();
900/// }
901/// ```
902///
903/// Benchmarking [options] set on parent groups cascade into child groups and
904/// their benchmarks:
905///
906/// ```
907/// #[divan::bench_group(
908///     sample_count = 100,
909///     sample_size = 500,
910/// )]
911/// mod parent {
912///     #[divan::bench_group(sample_size = 1)]
913///     mod child1 {
914///         #[divan::bench]
915///         fn bench() {
916///             // Will be sampled 100 times with 1 iteration per sample.
917///         }
918///     }
919///
920///     #[divan::bench_group(sample_count = 42)]
921///     mod child2 {
922///         #[divan::bench]
923///         fn bench() {
924///             // Will be sampled 42 times with 500 iterations per sample.
925///         }
926///     }
927///
928///     mod child3 {
929///         #[divan::bench(sample_count = 1)]
930///         fn bench() {
931///             // Will be sampled 1 time with 500 iterations per sample.
932///         }
933///     }
934/// }
935/// ```
936///
937/// Applying this attribute multiple times to the same item will cause a compile
938/// error:
939///
940/// ```compile_fail
941/// #[divan::bench_group]
942/// #[divan::bench_group]
943/// mod math {
944///     // ...
945/// }
946/// ```
947///
948/// # Options
949/// [options]: #options
950///
951/// - [`name`]
952/// - [`crate`]
953/// - [`sample_count`]
954/// - [`sample_size`]
955/// - [`threads`]
956/// - [`counters`]
957///     - [`bytes_count`]
958///     - [`chars_count`]
959///     - [`items_count`]
960/// - [`min_time`]
961/// - [`max_time`]
962/// - [`skip_ext_time`]
963/// - [`ignore`]
964///
965/// ## `name`
966/// [`name`]: #name
967///
968/// By default, the benchmark group uses the module's name. It can be overridden
969/// via the `name` option:
970///
971/// ```
972/// #[divan::bench_group(name = "my_math")]
973/// mod math {
974///     #[divan::bench(name = "my_add")]
975///     fn add() -> i32 {
976///         // Will appear as "crate_name::my_math::my_add".
977///         # 0
978///     }
979/// }
980/// ```
981///
982/// ## `crate`
983/// [`crate`]: #crate
984///
985/// The path to the specific `divan` crate instance used by this macro's
986/// generated code can be specified via the [`crate`] option. This is applicable
987/// when using `divan` via a macro from your own crate.
988///
989/// ```
990/// extern crate divan as sofa;
991///
992/// #[::sofa::bench_group(crate = ::sofa)]
993/// mod math {
994///     #[::sofa::bench(crate = ::sofa)]
995///     fn add() -> i32 {
996///         // ...
997///         # 0
998///     }
999/// }
1000/// ```
1001///
1002/// ## `sample_count`
1003/// [`sample_count`]: #sample_count
1004///
1005/// The number of statistical sample recordings can be set to a predetermined
1006/// [`u32`] value via the [`sample_count`] option. This may be overridden at
1007/// runtime using either the `DIVAN_SAMPLE_COUNT` environment variable or
1008/// `--sample-count` CLI argument.
1009///
1010/// ```
1011/// #[divan::bench_group(sample_count = 1000)]
1012/// mod math {
1013///     #[divan::bench]
1014///     fn add() -> i32 {
1015///         // ...
1016///         # 0
1017///     }
1018/// }
1019/// ```
1020///
1021/// If the [`threads`] option is enabled, sample count becomes a multiple of the
1022/// number of threads. This is because each thread operates over the same sample
1023/// size to ensure there are always N competing threads doing the same amount of
1024/// work.
1025///
1026/// ## `sample_size`
1027/// [`sample_size`]: #sample_size
1028///
1029/// The number iterations within each statistical sample can be set to a
1030/// predetermined [`u32`] value via the [`sample_size`] option. This may be
1031/// overridden at runtime using either the `DIVAN_SAMPLE_SIZE` environment
1032/// variable or `--sample-size` CLI argument.
1033///
1034/// ```
1035/// #[divan::bench_group(sample_size = 1000)]
1036/// mod math {
1037///     #[divan::bench]
1038///     fn add() -> i32 {
1039///         // ...
1040///         # 0
1041///     }
1042/// }
1043/// ```
1044///
1045/// ## `threads`
1046/// [`threads`]: #threads
1047///
1048/// See [`#[divan::bench(threads = ...)]`](macro@bench#threads).
1049///
1050/// ## `counters`
1051/// [`counters`]: #counters
1052///
1053/// The [`Counter`s](crate::counter::Counter) of each iteration of benchmarked
1054/// functions in a group can be set via the [`counters`] option. The following
1055/// example emits info for the number of bytes and number of ints processed when
1056/// benchmarking [slice sorting](slice::sort):
1057///
1058/// ```
1059/// use divan::{Bencher, counter::{BytesCount, ItemsCount}};
1060///
1061/// const INTS: &[i32] = &[
1062///     // ...
1063/// ];
1064///
1065/// #[divan::bench_group(counters = [
1066///     BytesCount::of_slice(INTS),
1067///     ItemsCount::new(INTS.len()),
1068/// ])]
1069/// mod sort {
1070///     use super::*;
1071///
1072///     #[divan::bench]
1073///     fn default(bencher: Bencher) {
1074///         bencher
1075///             .with_inputs(|| INTS.to_vec())
1076///             .bench_refs(|ints| ints.sort());
1077///     }
1078///
1079///     #[divan::bench]
1080///     fn unstable(bencher: Bencher) {
1081///         bencher
1082///             .with_inputs(|| INTS.to_vec())
1083///             .bench_refs(|ints| ints.sort_unstable());
1084///     }
1085/// }
1086/// # fn main() {}
1087/// ```
1088///
1089/// For convenience, singular `counter` allows a single
1090/// [`Counter`](crate::counter::Counter) to be set. The following example emits
1091/// info for the number of bytes processed when benchmarking
1092/// [`char`-counting](std::str::Chars::count) and
1093/// [`char`-collecting](std::str::Chars::collect):
1094///
1095/// ```
1096/// use divan::counter::BytesCount;
1097///
1098/// const STR: &str = "...";
1099///
1100/// #[divan::bench_group(counter = BytesCount::of_str(STR))]
1101/// mod chars {
1102///     use super::STR;
1103///
1104///     #[divan::bench]
1105///     fn count() -> usize {
1106///         divan::black_box(STR).chars().count()
1107///     }
1108///
1109///     #[divan::bench]
1110///     fn collect() -> String {
1111///         divan::black_box(STR).chars().collect()
1112///     }
1113/// }
1114/// # fn main() {}
1115/// ```
1116///
1117/// See:
1118/// - [`#[divan::bench(counters = ...)]`](macro@bench#counters)
1119/// - [`Bencher::counter`]
1120/// - [`Bencher::input_counter`]
1121///
1122/// ### `bytes_count`
1123/// [`bytes_count`]: #bytes_count
1124///
1125/// Convenience shorthand for
1126/// <code>[counter](#counters) = [BytesCount](counter::BytesCount)::from(n)</code>.
1127///
1128/// ### `chars_count`
1129/// [`chars_count`]: #chars_count
1130///
1131/// Convenience shorthand for
1132/// <code>[counter](#counters) = [CharsCount](counter::CharsCount)::from(n)</code>.
1133///
1134/// ### `cycles_count`
1135/// [`cycles_count`]: #cycles_count
1136///
1137/// Convenience shorthand for
1138/// <code>[counter](#counters) = [CyclesCount](counter::CyclesCount)::from(n)</code>.
1139///
1140/// ### `items_count`
1141/// [`items_count`]: #items_count
1142///
1143/// Convenience shorthand for
1144/// <code>[counter](#counters) = [ItemsCount](counter::ItemsCount)::from(n)</code>.
1145///
1146/// ## `min_time`
1147/// [`min_time`]: #min_time
1148///
1149/// The minimum time spent benchmarking each function can be set to a
1150/// predetermined [`Duration`] via the [`min_time`] option. This may be
1151/// overridden at runtime using either the `DIVAN_MIN_TIME` environment variable
1152/// or `--min-time` CLI argument.
1153///
1154/// Unless [`skip_ext_time`] is set, this includes time external to benchmarked
1155/// functions, such as time spent generating inputs and running [`Drop`].
1156///
1157/// ```
1158/// use std::time::Duration;
1159///
1160/// #[divan::bench_group(min_time = Duration::from_secs(3))]
1161/// mod math {
1162///     #[divan::bench]
1163///     fn add() -> i32 {
1164///         // ...
1165///         # 0
1166///     }
1167/// }
1168/// ```
1169///
1170/// For convenience, [`min_time`] can also be set with seconds as [`u64`] or
1171/// [`f64`]. Invalid values will cause a panic at runtime.
1172///
1173/// ```
1174/// #[divan::bench_group(min_time = 2)]
1175/// mod int_secs {
1176///     // ...
1177/// }
1178///
1179/// #[divan::bench_group(min_time = 1.5)]
1180/// mod float_secs {
1181///     // ...
1182/// }
1183/// ```
1184///
1185/// ## `max_time`
1186/// [`max_time`]: #max_time
1187///
1188/// The maximum time spent benchmarking each function can be set to a
1189/// predetermined [`Duration`] via the [`max_time`] option. This may be
1190/// overridden at runtime using either the `DIVAN_MAX_TIME` environment variable
1191/// or `--max-time` CLI argument.
1192///
1193/// Unless [`skip_ext_time`] is set, this includes time external to benchmarked
1194/// functions, such as time spent generating inputs and running [`Drop`].
1195///
1196/// If `min_time > max_time`, then [`max_time`] has priority and [`min_time`]
1197/// will not be reached.
1198///
1199/// ```
1200/// use std::time::Duration;
1201///
1202/// #[divan::bench_group(max_time = Duration::from_secs(5))]
1203/// mod math {
1204///     #[divan::bench]
1205///     fn add() -> i32 {
1206///         // ...
1207///         # 0
1208///     }
1209/// }
1210/// ```
1211///
1212/// For convenience, like [`min_time`], [`max_time`] can also be set with
1213/// seconds as [`u64`] or [`f64`]. Invalid values will cause a panic at runtime.
1214///
1215/// ```
1216/// #[divan::bench_group(max_time = 8)]
1217/// mod int_secs {
1218///     // ...
1219/// }
1220///
1221/// #[divan::bench_group(max_time = 9.5)]
1222/// mod float_secs {
1223///     // ...
1224/// }
1225/// ```
1226///
1227/// ## `skip_ext_time`
1228/// [`skip_ext_time`]: #skip_ext_time
1229///
1230/// By default, [`min_time`] and [`max_time`] include time external to
1231/// benchmarked functions, such as time spent generating inputs and running
1232/// [`Drop`]. Enabling the [`skip_ext_time`] option will instead make those
1233/// options only consider time spent within benchmarked functions. This may be
1234/// overridden at runtime using either the `DIVAN_SKIP_EXT_TIME` environment
1235/// variable or `--skip-ext-time` CLI argument.
1236///
1237/// In the following example, [`max_time`] only considers time spent running
1238/// `measured_function`:
1239///
1240/// ```
1241/// #[divan::bench_group(skip_ext_time)]
1242/// mod group {
1243///     # fn generate_input() {}
1244///     # fn measured_function(_: ()) {}
1245///     #[divan::bench(max_time = 5)]
1246///     fn bench(bencher: divan::Bencher) {
1247///         bencher
1248///             .with_inputs(|| generate_input())
1249///             .bench_values(|input| measured_function(input));
1250///     }
1251/// }
1252/// ```
1253///
1254/// This option can be set to an explicit [`bool`] value to override parent
1255/// values:
1256///
1257/// ```
1258/// #[divan::bench_group(skip_ext_time = false)]
1259/// mod group {
1260///     // ...
1261/// }
1262/// ```
1263///
1264/// ## `ignore`
1265/// [`ignore`]: #ignore
1266///
1267/// Like [`#[test]`](https://doc.rust-lang.org/reference/attributes/testing.html#the-test-attribute)
1268/// and [`#[divan::bench]`](macro@bench), `#[divan::bench_group]` functions can
1269/// use [`#[ignore]`](https://doc.rust-lang.org/reference/attributes/testing.html#the-ignore-attribute):
1270///
1271/// ```
1272/// #[divan::bench_group]
1273/// #[ignore]
1274/// mod math {
1275///     #[divan::bench]
1276///     fn todo() {
1277///         unimplemented!();
1278///     }
1279/// }
1280/// # divan::main();
1281/// ```
1282///
1283/// This option can also instead be set within the `#[divan::bench_group]`
1284/// attribute:
1285///
1286/// ```
1287/// #[divan::bench_group(ignore)]
1288/// mod math {
1289///     #[divan::bench]
1290///     fn todo() {
1291///         unimplemented!();
1292///     }
1293/// }
1294/// # divan::main();
1295/// ```
1296///
1297/// Like [`skip_ext_time`], this option can be set to an explicit [`bool`] value
1298/// to override parent values:
1299///
1300/// ```
1301/// #[divan::bench_group(ignore = false)]
1302/// mod group {
1303///     // ...
1304/// }
1305/// ```
1306///
1307/// This can be used to ignore benchmarks based on a runtime condition. The
1308/// following example benchmark group will be ignored if an [environment
1309/// variable](std::env::var) is not set to "true":
1310///
1311/// ```
1312/// #[divan::bench_group(
1313///     ignore = std::env::var("BENCH_EXPENSIVE").as_deref() != Ok("true")
1314/// )]
1315/// mod expensive_benches {
1316///     // ...
1317/// }
1318/// ```
1319///
1320/// [`Duration`]: std::time::Duration
1321pub use divan_macros::bench_group;