@@ -94,6 +94,81 @@ impl<'a, M: Measurement> Bencher<'a, M> {
9494 self . elapsed_time = time_start. elapsed ( ) ;
9595 }
9696
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+
97172 /// Times a `routine` by executing it many times and relying on `routine` to measure its own execution time.
98173 ///
99174 /// Prefer this timing loop in cases where `routine` has to do its own measurements to
0 commit comments