| 1 | use std::ptr::NonNull; |
| 2 | |
| 3 | use crate::{benchmark::BenchArgsRunner, Bencher}; |
| 4 | |
| 5 | mod generic; |
| 6 | mod list; |
| 7 | mod meta; |
| 8 | mod tree; |
| 9 | |
| 10 | pub use self::{ |
| 11 | generic::{EntryConst, EntryType, GenericBenchEntry}, |
| 12 | list::EntryList, |
| 13 | meta::{EntryLocation, EntryMeta}, |
| 14 | }; |
| 15 | pub(crate) use tree::EntryTree; |
| 16 | |
| 17 | /// Benchmark entries generated by `#[divan::bench]`. |
| 18 | /// |
| 19 | /// Note: generic-type benchmark entries are instead stored in `GROUP_ENTRIES` |
| 20 | /// in `generic_benches`. |
| 21 | pub static BENCH_ENTRIES: EntryList<BenchEntry> = EntryList::root(); |
| 22 | |
| 23 | /// Group entries generated by `#[divan::bench_group]`. |
| 24 | pub static GROUP_ENTRIES: EntryList<GroupEntry> = EntryList::root(); |
| 25 | |
| 26 | /// Determines how the benchmark entry is run. |
| 27 | #[derive (Clone, Copy)] |
| 28 | pub enum BenchEntryRunner { |
| 29 | /// Benchmark without arguments. |
| 30 | Plain(fn(Bencher)), |
| 31 | |
| 32 | /// Benchmark with runtime arguments. |
| 33 | Args(fn() -> BenchArgsRunner), |
| 34 | } |
| 35 | |
| 36 | /// Compile-time entry for a benchmark, generated by `#[divan::bench]`. |
| 37 | pub struct BenchEntry { |
| 38 | /// Entry metadata. |
| 39 | pub meta: EntryMeta, |
| 40 | |
| 41 | /// The benchmarking function. |
| 42 | pub bench: BenchEntryRunner, |
| 43 | } |
| 44 | |
| 45 | /// Compile-time entry for a benchmark group, generated by |
| 46 | /// `#[divan::bench_group]` or a generic-type `#[divan::bench]`. |
| 47 | pub struct GroupEntry { |
| 48 | /// Entry metadata. |
| 49 | pub meta: EntryMeta, |
| 50 | |
| 51 | /// Generic `#[divan::bench]` entries. |
| 52 | /// |
| 53 | /// This is two-dimensional to make code generation simpler. The outer |
| 54 | /// dimension corresponds to types and the inner dimension corresponds to |
| 55 | /// constants. |
| 56 | pub generic_benches: Option<&'static [&'static [GenericBenchEntry]]>, |
| 57 | } |
| 58 | |
| 59 | impl GroupEntry { |
| 60 | pub(crate) fn generic_benches_iter(&self) -> impl Iterator<Item = &'static GenericBenchEntry> { |
| 61 | self.generic_benches.unwrap_or_default().iter().flat_map(|benches: &&[GenericBenchEntry]| benches.iter()) |
| 62 | } |
| 63 | } |
| 64 | |
| 65 | /// `BenchEntry` or `GenericBenchEntry`. |
| 66 | #[derive (Clone, Copy)] |
| 67 | pub(crate) enum AnyBenchEntry<'a> { |
| 68 | Bench(&'a BenchEntry), |
| 69 | GenericBench(&'a GenericBenchEntry), |
| 70 | } |
| 71 | |
| 72 | impl<'a> AnyBenchEntry<'a> { |
| 73 | /// Returns a pointer to use as the identity of the entry. |
| 74 | #[inline ] |
| 75 | pub fn entry_addr(self) -> NonNull<()> { |
| 76 | match self { |
| 77 | Self::Bench(entry) => NonNull::from(entry).cast(), |
| 78 | Self::GenericBench(entry) => NonNull::from(entry).cast(), |
| 79 | } |
| 80 | } |
| 81 | |
| 82 | /// Returns this entry's benchmark runner. |
| 83 | #[inline ] |
| 84 | pub fn bench_runner(self) -> &'a BenchEntryRunner { |
| 85 | match self { |
| 86 | Self::Bench(BenchEntry { bench, .. }) |
| 87 | | Self::GenericBench(GenericBenchEntry { bench, .. }) => bench, |
| 88 | } |
| 89 | } |
| 90 | |
| 91 | /// Returns this entry's argument names. |
| 92 | #[inline ] |
| 93 | pub fn arg_names(self) -> Option<&'static [&'static str]> { |
| 94 | match self.bench_runner() { |
| 95 | BenchEntryRunner::Args(bench_runner) => { |
| 96 | let bench_runner = bench_runner(); |
| 97 | Some(bench_runner.arg_names()) |
| 98 | } |
| 99 | _ => None, |
| 100 | } |
| 101 | } |
| 102 | |
| 103 | #[inline ] |
| 104 | pub fn meta(self) -> &'a EntryMeta { |
| 105 | match self { |
| 106 | Self::Bench(entry) => &entry.meta, |
| 107 | Self::GenericBench(entry) => &entry.group.meta, |
| 108 | } |
| 109 | } |
| 110 | |
| 111 | #[inline ] |
| 112 | pub fn raw_name(self) -> &'a str { |
| 113 | match self { |
| 114 | Self::Bench(entry) => entry.meta.raw_name, |
| 115 | Self::GenericBench(entry) => entry.raw_name(), |
| 116 | } |
| 117 | } |
| 118 | |
| 119 | #[inline ] |
| 120 | pub fn display_name(self) -> &'a str { |
| 121 | match self { |
| 122 | Self::Bench(entry) => entry.meta.display_name, |
| 123 | Self::GenericBench(entry) => entry.display_name(), |
| 124 | } |
| 125 | } |
| 126 | } |
| 127 | |