@@ -94,6 +94,81 @@ impl<'a, M: Measurement> Bencher<'a, M> {
94
94
self . elapsed_time = time_start. elapsed ( ) ;
95
95
}
96
96
97
+ /// Times a `routine` by executing it many times and timing the total elapsed time.
98
+ ///
99
+ /// Prefer this timing loop when `routine` returns a value that can be reused in
100
+ /// the next iteration.
101
+ ///
102
+ /// # Timing model
103
+ ///
104
+ /// Note that the `Bencher` also times the time required to move a value from one call to another.
105
+ /// Therefore prefer this timing loop when the runtime of this movement is negligible.
106
+ ///
107
+ /// ```text
108
+ /// elapsed = Instant::now + iters * (routine + Range::next)
109
+ /// ```
110
+ ///
111
+ /// # Example
112
+ ///
113
+ /// ```rust
114
+ /// use criterion::{criterion_group, criterion_main, Criterion};
115
+ ///
116
+ /// const HANDLE_COUNT: usize = 100;
117
+ ///
118
+ /// fn spawn_task(f: impl FnOnce() -> Vec<usize>) {
119
+ /// todo!()
120
+ /// }
121
+ ///
122
+ /// fn await_task() -> Vec<usize> {
123
+ /// todo!()
124
+ /// }
125
+ ///
126
+ /// // The function to benchmark that accept, use and returns a empty vector of a certain length
127
+ /// fn spawn_and_await(mut vec: Vec<usize>) -> Vec<usize> {
128
+ /// // move to closure
129
+ /// spawn_task(move || {
130
+ /// // use vec here and return
131
+ /// vec
132
+ /// });
133
+ ///
134
+ /// // move back
135
+ /// let mut vec = await_task();
136
+ /// vec.clear();
137
+ ///
138
+ /// vec
139
+ /// }
140
+ ///
141
+ /// fn bench(c: &mut Criterion) {
142
+ /// c.bench_function("iter", move |b| {
143
+ /// b.iter_reuse(Vec::with_capacity(HANDLE_COUNT), |vec| spawn_and_await(vec))
144
+ /// });
145
+ /// }
146
+ ///
147
+ /// criterion_group!(benches, bench);
148
+ /// criterion_main!(benches);
149
+ /// ```
150
+ ///
151
+ #[ inline( never) ]
152
+ pub fn iter_reuse < IO , R > ( & mut self , input : IO , mut routine : R )
153
+ where
154
+ R : FnMut ( IO ) -> IO ,
155
+ {
156
+ self . iterated = true ;
157
+
158
+ let time_start = Instant :: now ( ) ;
159
+ let start = self . measurement . start ( ) ;
160
+
161
+ let mut input_output = input;
162
+ for _ in 0 ..self . iters {
163
+ input_output = black_box ( routine ( input_output) ) ;
164
+ }
165
+
166
+ self . value = self . measurement . end ( start) ;
167
+ self . elapsed_time = time_start. elapsed ( ) ;
168
+
169
+ black_box ( drop ( input_output) ) ;
170
+ }
171
+
97
172
/// Times a `routine` by executing it many times and relying on `routine` to measure its own execution time.
98
173
///
99
174
/// Prefer this timing loop in cases where `routine` has to do its own measurements to
0 commit comments