| 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 | |