Skip to main content

mobench_sdk/
registry.rs

1//! Benchmark function registry
2//!
3//! This module provides runtime discovery of benchmark functions that have been
4//! marked with the `#[benchmark]` attribute macro.
5
6use crate::timing::{BenchReport, BenchSpec, TimingError};
7
8/// A registered benchmark function
9///
10/// This struct is submitted to the global registry by the `#[benchmark]` macro.
11/// It contains the function's name and a runner that executes the benchmark.
12pub struct BenchFunction {
13    /// Fully-qualified name of the benchmark function (e.g., "my_crate::my_module::my_bench")
14    pub name: &'static str,
15
16    /// Runner function that executes the benchmark with timing
17    ///
18    /// Takes a BenchSpec and returns a BenchReport directly.
19    /// The runner handles setup/teardown internally.
20    pub runner: fn(BenchSpec) -> Result<BenchReport, TimingError>,
21}
22
23// Register the BenchFunction type with inventory
24inventory::collect!(BenchFunction);
25
26/// Discovers all registered benchmark functions
27///
28/// Returns a vector of references to all functions that have been marked with
29/// the `#[benchmark]` attribute in the current binary.
30///
31/// # Example
32///
33/// ```no_run
34/// use mobench_sdk::registry::discover_benchmarks;
35///
36/// fn main() {
37///     let benchmarks = discover_benchmarks();
38///     for bench in benchmarks {
39///         println!("Found benchmark: {}", bench.name);
40///     }
41/// }
42/// ```
43pub fn discover_benchmarks() -> Vec<&'static BenchFunction> {
44    inventory::iter::<BenchFunction>().collect()
45}
46
47/// Finds a benchmark function by name
48///
49/// Searches the registry for a function with the given name. Supports both
50/// short names (e.g., "fibonacci") and fully-qualified names
51/// (e.g., "my_crate::fibonacci").
52///
53/// # Arguments
54///
55/// * `name` - The name of the benchmark to find
56///
57/// # Returns
58///
59/// * `Some(&BenchFunction)` if found
60/// * `None` if no matching benchmark exists
61///
62/// # Example
63///
64/// ```no_run
65/// use mobench_sdk::registry::find_benchmark;
66///
67/// fn main() {
68///     if let Some(bench) = find_benchmark("fibonacci") {
69///         println!("Found benchmark: {}", bench.name);
70///     } else {
71///         eprintln!("Benchmark not found");
72///     }
73/// }
74/// ```
75pub fn find_benchmark(name: &str) -> Option<&'static BenchFunction> {
76    inventory::iter::<BenchFunction>().find(|f| {
77        // Match either the full name or just the final component
78        f.name == name || f.name.ends_with(&format!("::{}", name))
79    })
80}
81
82/// Lists all registered benchmark names
83///
84/// Returns a sorted vector of all benchmark function names in the registry.
85///
86/// # Example
87///
88/// ```no_run
89/// use mobench_sdk::registry::list_benchmark_names;
90///
91/// fn main() {
92///     let names = list_benchmark_names();
93///     println!("Available benchmarks:");
94///     for name in names {
95///         println!("  - {}", name);
96///     }
97/// }
98/// ```
99pub fn list_benchmark_names() -> Vec<&'static str> {
100    let mut names: Vec<&'static str> = inventory::iter::<BenchFunction>().map(|f| f.name).collect();
101    names.sort();
102    names
103}
104
105#[cfg(test)]
106mod tests {
107    use super::*;
108
109    #[test]
110    fn test_discover_benchmarks() {
111        // Note: This test validates that the discovery function works
112        // The number of benchmarks depends on what's registered in the binary
113        let benchmarks = discover_benchmarks();
114        // Just ensure the function returns successfully
115        let _ = benchmarks;
116    }
117
118    #[test]
119    fn test_find_benchmark_none() {
120        // Should not find a non-existent benchmark
121        let result = find_benchmark("nonexistent_benchmark_function_12345");
122        assert!(result.is_none());
123    }
124
125    #[test]
126    fn test_list_benchmark_names() {
127        // Validates that the function returns successfully
128        let names = list_benchmark_names();
129        let _ = names;
130    }
131}