diff --git a/src/libcore/benches/iter.rs b/src/libcore/benches/iter.rs index 93d38a5bc83..5b06229c21f 100644 --- a/src/libcore/benches/iter.rs +++ b/src/libcore/benches/iter.rs @@ -99,3 +99,50 @@ fn bench_zip_add(b: &mut Bencher) { add_zip(&source, &mut dst) }); } + +/// `Iterator::for_each` implemented as a plain loop. +fn for_each_loop(iter: I, mut f: F) where + I: Iterator, F: FnMut(I::Item) +{ + for item in iter { + f(item); + } +} + +/// `Iterator::for_each` implemented with `fold` for internal iteration. +/// (except when `by_ref()` effectively disables that optimization.) +fn for_each_fold(iter: I, mut f: F) where + I: Iterator, F: FnMut(I::Item) +{ + iter.fold((), move |(), item| f(item)); +} + +#[bench] +fn bench_for_each_chain_loop(b: &mut Bencher) { + b.iter(|| { + let mut acc = 0; + let iter = (0i64..1000000).chain(0..1000000).map(black_box); + for_each_loop(iter, |x| acc += x); + acc + }); +} + +#[bench] +fn bench_for_each_chain_fold(b: &mut Bencher) { + b.iter(|| { + let mut acc = 0; + let iter = (0i64..1000000).chain(0..1000000).map(black_box); + for_each_fold(iter, |x| acc += x); + acc + }); +} + +#[bench] +fn bench_for_each_chain_ref_fold(b: &mut Bencher) { + b.iter(|| { + let mut acc = 0; + let mut iter = (0i64..1000000).chain(0..1000000).map(black_box); + for_each_fold(iter.by_ref(), |x| acc += x); + acc + }); +} diff --git a/src/libcore/iter/iterator.rs b/src/libcore/iter/iterator.rs index 49c43d133e5..d38864f3edd 100644 --- a/src/libcore/iter/iterator.rs +++ b/src/libcore/iter/iterator.rs @@ -487,7 +487,9 @@ pub trait Iterator { /// This is equivalent to using a [`for`] loop on the iterator, although /// `break` and `continue` are not possible from a closure. It's generally /// more idiomatic to use a `for` loop, but `for_each` may be more legible - /// when processing items at the end of longer iterator chains. + /// when processing items at the end of longer iterator chains. In some + /// cases `for_each` may also be faster than a loop, because it will use + /// internal iteration on adaptors like `Chain`. /// /// [`for`]: ../../book/first-edition/loops.html#for /// @@ -523,9 +525,7 @@ pub trait Iterator { fn for_each(self, mut f: F) where Self: Sized, F: FnMut(Self::Item), { - for item in self { - f(item); - } + self.fold((), move |(), item| f(item)); } /// Creates an iterator which uses a closure to determine if an element