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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
use NestedMeta;
use ;
use TokenStream;
use quote;
/// Annotation for the benchmark function.
///
/// The annotated function will be invoked for **N** iterations at a time in a loop.
///
/// Iterations **0** ~ **N-2** will be used for warm-up, and the last iteration (**N-1**) will be used for measurement.
///
/// Each iteration has three phases:
/// 1. **Prepare**: Prepare any data or resources needed for this iteration.
/// 2. **Timing**: Perform the actual work. This should be wrapped in a call to `bencher.time()`.
/// 3. **Release**: Clean up any data or resources, and perform any necessary result checks.
///
/// **Note:**: Each benchmark file should contain exactly one benchmark function.
///
/// # Example
///
/// ```rust
/// use harness::{bench, Bencher, black_box};
///
/// const LEN: usize = 10000000;
///
/// #[bench]
/// fn example(bencher: &Bencher) {
/// // Prepare the inputs
/// let mut list = black_box((0..1000).collect::<Vec<_>>());
/// // Actual work. For the last timing iteration only this part will be measured.
/// let result = bencher.time(|| {
/// // Do some work here
/// list.iter().sum::<usize>()
/// });
/// // Release the resources and check the result
/// assert_eq!(result, LEN * (LEN - 1) / 2)
/// }
/// ```
///
/// # Startup and Teardown
///
/// To run some extra code _once_ before and after the benchmark, please use the `startup` and `teardown` hooks in the attributes.
///
/// `startup` is called ones before all the iterations, and `teardown` is called once after all the iterations.
///
/// ```rust
/// use harness::{bench, Bencher, black_box};
///
/// fn example_startup() {
/// // TODO: Pre-benchmark initialization. e.g. Download data for the benchmark.
/// }
///
/// fn example_teardown() {
/// // TODO: After benchmark cleanups. e.g. Delete the downloaded data.
/// }
///
/// const LEN: usize = 10000000;
///
/// #[bench(startup = example_startup, teardown = example_teardown)]
/// fn example(bencher: &Bencher) {
/// // Prepare the inputs
/// let mut list = black_box((0..LEN).collect::<Vec<_>>());
/// // Actual work. For the last timing iteration only this part will be measured.
/// let result = bencher.time(|| {
/// // Do some work here
/// list.iter().sum::<usize>()
/// });
/// // Release the resources and check the result
/// assert_eq!(result, LEN * (LEN - 1) / 2)
/// }
/// ````
/// Annotation for the harness probe struct.