1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
//! A benchmarking library for Rust libraries
//!
//! This crate provides measurement facilities for rust libraries. For now only time measurements
//! are supported. Next step will be to support disk , CPU and memory usage
//!
//! Each benchmark is repeated `repeat` times for every workload point after it was ramped up for
//! the same workload point. Any type `W: Clone + Display` can be used to specify workloads. It could
//! be an integer that specifies the size of the workload, a path to a file or a key that we can use
//! to fetch the workload from the benchmark configuration. See examples below.
//!
//! ## Examples
//! A simple benchmark that measures execution time for increasing workloads. In this case the workload is simulated by
//! by a `u64` value passed to `thread::sleep` function
//! ```rust
//! mod example {
//!     use std::thread;
//!     use std::time::Duration;
//!     use benchmark_rs::{Benchmarks, StopWatch};
//!
//!     fn example(_stop_watch: &mut StopWatch, _config: &str, work: u64) -> Result<(), anyhow::Error> {
//!         thread::sleep(Duration::from_millis(work));
//!         Ok(())
//!     }
//!
//!     #[test]
//!     fn benchmark_example() -> Result<(), anyhow::Error> {
//!         let mut benchmarks = Benchmarks::new("Example");
//!         benchmarks.add("A Simple Benchmark", example, "No Configuration", (1..=10).collect(), 2, 1)?;
//!         benchmarks.run()?;
//!
//!         let summary = benchmarks.summary_as_json();
//!         println!("Summary: {summary}");
//!         Ok(())
//!     }
//! }
//! ```
//!
//! A more complex example that shows how to use Benchmark configuration, how to control the
//! stopwatch from within the benchmark, and how to show and analyze results.
//! ```rust
//! mod another_example {
//!     use std::collections::{BTreeMap};
//!     use std::fmt::{Display, Formatter};
//!     use std::thread;
//!     use std::time::Duration;
//!     use benchmark_rs::{Benchmarks, StopWatch};
//!
//!     #[derive(Clone)]
//!     struct Config {
//!         pub workloads: BTreeMap<u64, Duration>,
//!     }
//!
//!     impl Display for Config {
//!         fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
//!             for k in self.workloads.keys() {
//!                 write!(f, "{k} ")?;
//!             }
//!             Ok(())
//!         }
//!     }
//!
//!     fn example(stop_watch: &mut StopWatch, config: Config, work: u64) -> Result<(), anyhow::Error> {
//!         stop_watch.pause();
//!         // perform potentially lengthy preparation that will not reflect in the measurement
//!         let sleep_time = config.workloads.get(&work).unwrap().clone();
//!         stop_watch.resume();
//!         // perform measured computation
//!         thread::sleep(sleep_time);
//!         stop_watch.pause();
//!         // perform potentially lengthy cleanup
//!         Ok(())
//!     }
//!
//!     #[test]
//!     fn another_benchmark_example() -> Result<(), anyhow::Error> {
//!         let mut benchmarks = Benchmarks::new("Example");
//!         let workloads: BTreeMap<u64, Duration> = (0..=10).map(|i| (i, Duration::from_millis(i))).collect();
//!         benchmarks.add("Another Benchmark", example, Config { workloads }, (1..=10).collect(), 2, 1)?;
//!         benchmarks.run()?;
//!
//!         let summary = benchmarks.summary_as_json();
//!         println!("Summary: {summary}");
//!         let csv_headers = benchmarks.csv_headers();
//!         let csv_data = benchmarks.summary_as_csv();
//!         for (k, v) in csv_data {
//!             println!("Benchmark name: {k}");
//!             println!("{csv_headers}");
//!             for line in v {
//!                 println!("{line}")
//!             }
//!         }
//!
//!         // ignore new series
//!         let analysis_result = benchmarks.analyze(None, 5.0)?;
//!         println!("Analysis result: {}", analysis_result.to_string());
//!         // compare results with threshold of 5 percent
//!         let analysis_result = benchmarks.analyze(Some(summary), 5.0)?;
//!         println!("Analysis result: {}", analysis_result.to_string());
//!         Ok(())
//!     }
//! }
//!
pub mod benchmarks;
pub mod benchmark_comparison;
pub mod summary;
pub mod benchmark;
pub mod run_summary;
pub mod analysis_result;
pub mod stopwatch;
pub mod disk_usage;
pub mod series_summary;

pub type Benchmarks<C, W, E> = benchmarks::Benchmarks<C, W, E>;
pub type BenchmarkComparison = benchmark_comparison::BenchmarkComparison;
pub type StopWatch = stopwatch::StopWatch;
pub type Summary = summary::Summary;
pub type RunSummary = run_summary::RunSummary;
pub type SeriesSummary = series_summary::SeriesSummary;