From fbe5aa57ed810733f2fd4047cf5e5c24aebd8b01 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Sat, 8 Dec 2018 20:09:44 +0900 Subject: [PATCH 1/3] Override Cycle::try_fold name old ns/iter new ns/iter diff ns/iter diff % speedup iter::bench_cycle_take_ref_sum 927,152 927,194 42 0.00% x 1.00 iter::bench_cycle_take_sum 938,129 603,492 -334,637 -35.67% x 1.55 --- src/libcore/benches/iter.rs | 6 ++++++ src/libcore/iter/mod.rs | 13 +++++++++++++ src/libcore/tests/iter.rs | 2 ++ 3 files changed, 21 insertions(+) diff --git a/src/libcore/benches/iter.rs b/src/libcore/benches/iter.rs index 6c597301ac2..b0aca658343 100644 --- a/src/libcore/benches/iter.rs +++ b/src/libcore/benches/iter.rs @@ -282,6 +282,12 @@ bench_sums! { (0i64..1000000).chain(1000000..).take_while(|&x| x < 1111111) } +bench_sums! { + bench_cycle_take_sum, + bench_cycle_take_ref_sum, + (0i64..10000).cycle().take(1000000) +} + // Checks whether Skip> is as fast as Zip, Skip>, from // https://users.rust-lang.org/t/performance-difference-between-iterator-zip-and-skip-order/15743 #[bench] diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index de7ab8843da..83d35324bc2 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -649,6 +649,19 @@ impl Iterator for Cycle where I: Clone + Iterator { _ => (usize::MAX, None) } } + + #[inline] + fn try_fold(&mut self, init: Acc, mut f: F) -> R where + Self: Sized, F: FnMut(Acc, Self::Item) -> R, R: Try + { + let mut accum = init; + while let Some(x) = self.iter.next() { + accum = f(accum, x)?; + accum = self.iter.try_fold(accum, &mut f)?; + self.iter = self.orig.clone(); + } + Try::from_ok(accum) + } } #[stable(feature = "fused", since = "1.26.0")] diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs index 19be1a07c5b..4efa0136314 100644 --- a/src/libcore/tests/iter.rs +++ b/src/libcore/tests/iter.rs @@ -1001,6 +1001,8 @@ fn test_cycle() { let mut it = (0..).step_by(1).take(0).cycle(); assert_eq!(it.size_hint(), (0, Some(0))); assert_eq!(it.next(), None); + + assert_eq!(empty::().cycle().fold(0, |acc, x| acc + x), 0); } #[test] From e704ce9e8af1713eb938a9acd7f27bf96f88664e Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Sat, 8 Dec 2018 20:15:49 +0900 Subject: [PATCH 2/3] Resolve FIXME and cleanup --- src/libcore/iter/mod.rs | 27 +++++++-------------------- src/libcore/lib.rs | 1 + 2 files changed, 8 insertions(+), 20 deletions(-) diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index 83d35324bc2..bc5bbc2217c 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -1868,18 +1868,11 @@ impl Iterator for Peekable { #[inline] fn nth(&mut self, n: usize) -> Option { - // FIXME(#43234): merge these when borrow-checking gets better. - if n == 0 { - match self.peeked.take() { - Some(v) => v, - None => self.iter.nth(n), - } - } else { - match self.peeked.take() { - Some(None) => None, - Some(Some(_)) => self.iter.nth(n - 1), - None => self.iter.nth(n), - } + match self.peeked.take() { + Some(None) => None, + Some(v @ Some(_)) if n == 0 => v, + Some(Some(_)) => self.iter.nth(n - 1), + None => self.iter.nth(n), } } @@ -1978,14 +1971,8 @@ impl Peekable { #[inline] #[stable(feature = "rust1", since = "1.0.0")] pub fn peek(&mut self) -> Option<&I::Item> { - if self.peeked.is_none() { - self.peeked = Some(self.iter.next()); - } - match self.peeked { - Some(Some(ref value)) => Some(value), - Some(None) => None, - _ => unreachable!(), - } + let iter = &mut self.iter; + self.peeked.get_or_insert_with(|| iter.next()).as_ref() } } diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs index 726e891df0c..1287e11cff4 100644 --- a/src/libcore/lib.rs +++ b/src/libcore/lib.rs @@ -92,6 +92,7 @@ #![feature(link_llvm_intrinsics)] #![feature(never_type)] #![feature(nll)] +#![feature(bind_by_move_pattern_guards)] #![feature(exhaustive_patterns)] #![feature(no_core)] #![feature(on_unimplemented)] From 5728a043e8280e96cbae784a731d43f2c7a50137 Mon Sep 17 00:00:00 2001 From: Shotaro Yamada Date: Sat, 8 Dec 2018 20:16:36 +0900 Subject: [PATCH 3/3] Don't call size_hint of underlying iterator needlessly --- src/libcore/iter/mod.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index bc5bbc2217c..7b273f7862a 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -2109,8 +2109,12 @@ impl Iterator for TakeWhile #[inline] fn size_hint(&self) -> (usize, Option) { - let (_, upper) = self.iter.size_hint(); - (0, upper) // can't know a lower bound, due to the predicate + if self.flag { + (0, Some(0)) + } else { + let (_, upper) = self.iter.size_hint(); + (0, upper) // can't know a lower bound, due to the predicate + } } #[inline] @@ -2321,6 +2325,10 @@ impl Iterator for Take where I: Iterator{ #[inline] fn size_hint(&self) -> (usize, Option) { + if self.n == 0 { + return (0, Some(0)); + } + let (lower, upper) = self.iter.size_hint(); let lower = cmp::min(lower, self.n);