1 | use std::{borrow::Cow, time::Duration}; |
2 | |
3 | use crate::{counter::CounterSet, time::FineDuration}; |
4 | |
5 | /// Benchmarking options set directly by the user in `#[divan::bench]` and |
6 | /// `#[divan::bench_group]`. |
7 | /// |
8 | /// Changes to fields must be reflected in the "Options" sections of the docs |
9 | /// for `#[divan::bench]` and `#[divan::bench_group]`. |
10 | #[derive (Clone, Default)] |
11 | pub struct BenchOptions<'a> { |
12 | /// The number of sample recordings. |
13 | pub sample_count: Option<u32>, |
14 | |
15 | /// The number of iterations inside a single sample. |
16 | pub sample_size: Option<u32>, |
17 | |
18 | /// The number of threads to benchmark the sample. This is 1 by default. |
19 | /// |
20 | /// If set to 0, this will use [`std::thread::available_parallelism`]. |
21 | /// |
22 | /// We use `&'static [usize]` by leaking the input because `BenchOptions` is |
23 | /// cached on first retrieval. |
24 | pub threads: Option<Cow<'a, [usize]>>, |
25 | |
26 | /// Counts the number of values processed each iteration of a benchmarked |
27 | /// function. |
28 | pub counters: CounterSet, |
29 | |
30 | /// The time floor for benchmarking a function. |
31 | pub min_time: Option<Duration>, |
32 | |
33 | /// The time ceiling for benchmarking a function. |
34 | pub max_time: Option<Duration>, |
35 | |
36 | /// When accounting for `min_time` or `max_time`, skip time external to |
37 | /// benchmarked functions, such as time spent generating inputs and running |
38 | /// [`Drop`]. |
39 | pub skip_ext_time: Option<bool>, |
40 | |
41 | /// Whether the benchmark should be ignored. |
42 | /// |
43 | /// This may be set within the attribute or with a separate |
44 | /// [`#[ignore]`](https://doc.rust-lang.org/reference/attributes/testing.html#the-ignore-attribute). |
45 | pub ignore: Option<bool>, |
46 | } |
47 | |
48 | impl<'a> BenchOptions<'a> { |
49 | /// Overwrites `other` with values set in `self`. |
50 | #[must_use ] |
51 | pub(crate) fn overwrite<'b>(&'b self, other: &'b Self) -> Self |
52 | where |
53 | 'b: 'a, |
54 | { |
55 | Self { |
56 | // `Copy` values: |
57 | sample_count: self.sample_count.or(other.sample_count), |
58 | sample_size: self.sample_size.or(other.sample_size), |
59 | threads: self.threads.as_deref().or(other.threads.as_deref()).map(Cow::Borrowed), |
60 | min_time: self.min_time.or(other.min_time), |
61 | max_time: self.max_time.or(other.max_time), |
62 | skip_ext_time: self.skip_ext_time.or(other.skip_ext_time), |
63 | ignore: self.ignore.or(other.ignore), |
64 | |
65 | // `Clone` values: |
66 | counters: self.counters.overwrite(&other.counters), |
67 | } |
68 | } |
69 | |
70 | /// Returns `true` if non-zero samples are specified. |
71 | #[inline ] |
72 | pub(crate) fn has_samples(&self) -> bool { |
73 | self.sample_count != Some(0) && self.sample_size != Some(0) |
74 | } |
75 | |
76 | #[inline ] |
77 | pub(crate) fn min_time(&self) -> FineDuration { |
78 | self.min_time.map(FineDuration::from).unwrap_or_default() |
79 | } |
80 | |
81 | #[inline ] |
82 | pub(crate) fn max_time(&self) -> FineDuration { |
83 | self.max_time.map(FineDuration::from).unwrap_or(FineDuration::MAX) |
84 | } |
85 | } |
86 | |