Skip to content

Commit 6879a4c

Browse files
committed
Specialize consume_iter for simple std::iter-like consumers
These consumers all exist as std::iter adaptors too (except for `update`, but that one is very simple), and so we can specialize `consume_iter` to call them, to potentially benefit from any internal iteration optimizations they have. Part of rayon-rs#465. The following example gets 8x faster (1.6s before, 0.2s after), on a 6 core (12 threads) machine: ``` extern crate test; extern crate rayon; use rayon::prelude::*; fn main() { let count = (0..std::u32::MAX).into_par_iter().map(test::black_box).count(); println!("{}", count); } ``` For the built-in benchmarks, there doesn't seem to be any true slow-downs (some benchmarks are so variable that it's very hard to accurately determine the change), and a lot of speed-ups. This affects the `find` and `collect` benchmarks the most: ``` name find-old.txt ns/iter find-new.txt ns/iter diff ns/iter diff % speedup find::size1::parallel_find_first 19,329 20,003 674 3.49% x 0.97 find::size1::parallel_find_common 24,328 23,183 -1,145 -4.71% x 1.05 find::size1::parallel_find_missing 2,131,717 1,687,769 -443,948 -20.83% x 1.26 find::size1::parallel_find_last 1,606,984 1,201,934 -405,050 -25.21% x 1.34 find::size1::parallel_find_middle 1,242,411 819,751 -422,660 -34.02% x 1.52 ``` ``` name collect-old.txt ns/iter collect-new.txt ns/iter diff ns/iter diff % speedup map_collect::i_to_i::with_mutex_vec 30,813,044 31,650,037 836,993 2.72% x 0.97 map_collect::i_to_i::with_linked_list_collect_vec_sized 12,769,089 13,077,052 307,963 2.41% x 0.98 map_collect::i_mod_10_to_i::with_mutex_vec 8,222,478 8,316,029 93,551 1.14% x 0.99 map_collect::i_to_i::with_fold 49,522,357 49,662,761 140,404 0.28% x 1.00 map_collect::i_to_i::with_linked_list_collect 31,901,399 31,558,372 -343,027 -1.08% x 1.01 map_collect::i_mod_10_to_i::with_linked_list_collect 21,974,395 21,622,942 -351,453 -1.60% x 1.02 vec_collect::vec_i::with_fold 35,716,513 34,863,214 -853,299 -2.39% x 1.02 map_collect::i_to_i::with_fold_vec 51,523,306 50,049,271 -1,474,035 -2.86% x 1.03 map_collect::i_to_i::with_linked_list_collect_vec 23,086,079 22,443,957 -642,122 -2.78% x 1.03 map_collect::i_mod_10_to_i::with_mutex 80,962,611 77,863,092 -3,099,519 -3.83% x 1.04 map_collect::i_to_i::with_mutex 204,617,301 196,787,223 -7,830,078 -3.83% x 1.04 vec_collect::vec_i::with_collect 2,535,582 2,437,613 -97,969 -3.86% x 1.04 vec_collect::vec_i::with_collect_into_vec 2,665,272 2,531,158 -134,114 -5.03% x 1.05 map_collect::i_to_i::with_vec_vec_sized 14,525,832 13,627,798 -898,034 -6.18% x 1.07 vec_collect::vec_i::with_collect_into_vec_reused 1,227,069 1,109,099 -117,970 -9.61% x 1.11 vec_collect::vec_i_filtered::with_fold 41,675,555 36,487,521 -5,188,034 -12.45% x 1.14 map_collect::i_mod_10_to_i::with_collect 6,068,716 5,130,790 -937,926 -15.46% x 1.18 map_collect::i_mod_10_to_i::with_vec_vec_sized 6,249,221 5,276,541 -972,680 -15.56% x 1.18 map_collect::i_mod_10_to_i::with_linked_list_collect_vec 5,996,844 5,026,503 -970,341 -16.18% x 1.19 map_collect::i_mod_10_to_i::with_linked_list_map_reduce_vec_sized 5,897,802 4,976,394 -921,408 -15.62% x 1.19 map_collect::i_to_i::with_collect 14,137,451 11,812,855 -2,324,596 -16.44% x 1.20 map_collect::i_mod_10_to_i::with_linked_list_collect_vec_sized 6,187,408 4,996,645 -1,190,763 -19.24% x 1.24 map_collect::i_to_i::with_linked_list_map_reduce_vec_sized 14,489,709 11,024,575 -3,465,134 -23.91% x 1.31 map_collect::i_mod_10_to_i::with_fold 1,690,818 1,265,901 -424,917 -25.13% x 1.34 vec_collect::vec_i::with_linked_list_collect_vec 23,295,026 16,697,819 -6,597,207 -28.32% x 1.40 map_collect::i_mod_10_to_i::with_fold_vec 2,652,629 1,707,870 -944,759 -35.62% x 1.55 vec_collect::vec_i::with_linked_list_map_reduce_vec_sized 14,930,174 9,183,037 -5,747,137 -38.49% x 1.63 vec_collect::vec_i::with_vec_vec_sized 15,782,752 9,705,671 -6,077,081 -38.50% x 1.63 vec_collect::vec_i_filtered::with_linked_list_collect_vec 30,026,717 18,254,188 -11,772,529 -39.21% x 1.64 vec_collect::vec_i::with_linked_list_collect_vec_sized 15,408,185 8,607,308 -6,800,877 -44.14% x 1.79 vec_collect::vec_i_filtered::with_vec_vec_sized 22,714,855 9,594,991 -13,119,864 -57.76% x 2.37 vec_collect::vec_i_filtered::with_linked_list_map_reduce_vec_sized 23,022,071 9,483,549 -13,538,522 -58.81% x 2.43 vec_collect::vec_i_filtered::with_linked_list_collect_vec_sized 23,143,333 9,342,023 -13,801,310 -59.63% x 2.48 vec_collect::vec_i_filtered::with_collect 24,671,619 6,026,401 -18,645,218 -75.57% x 4.09 ```
1 parent 346bcdf commit 6879a4c

File tree

8 files changed

+72
-0
lines changed

8 files changed

+72
-0
lines changed

src/iter/cloned.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,14 @@ where
205205
}
206206
}
207207

208+
fn consume_iter<I>(mut self, iter: I) -> Self
209+
where
210+
I: IntoIterator<Item = &'a T>
211+
{
212+
self.base = self.base.consume_iter(iter.into_iter().cloned());
213+
self
214+
}
215+
208216
fn complete(self) -> F::Result {
209217
self.base.complete()
210218
}

src/iter/filter.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,15 @@ where
136136
}
137137
}
138138

139+
fn consume_iter<I>(mut self, iter: I) -> Self
140+
where
141+
I: IntoIterator<Item = T>
142+
{
143+
self.base = self.base.consume_iter(iter.into_iter().filter(self.filter_op));
144+
self
145+
}
146+
147+
139148
fn complete(self) -> Self::Result {
140149
self.base.complete()
141150
}

src/iter/filter_map.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,13 @@ where
139139
self
140140
}
141141
}
142+
fn consume_iter<I>(mut self, iter: I) -> Self
143+
where
144+
I: IntoIterator<Item = T>
145+
{
146+
self.base = self.base.consume_iter(iter.into_iter().filter_map(self.filter_op));
147+
self
148+
}
142149

143150
fn complete(self) -> C::Result {
144151
self.base.complete()

src/iter/find.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,16 @@ where
8686
self
8787
}
8888

89+
fn consume_iter<I>(mut self, iter: I) -> Self
90+
where I: IntoIterator<Item = T>
91+
{
92+
self.item = iter.into_iter().find(self.find_op);
93+
if self.item.is_some() {
94+
self.found.store(true, Ordering::Relaxed)
95+
}
96+
self
97+
}
98+
8999
fn complete(self) -> Self::Result {
90100
self.item
91101
}

src/iter/fold.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,14 @@ where
141141
}
142142
}
143143

144+
fn consume_iter<I>(mut self, iter: I) -> Self
145+
where
146+
I: IntoIterator<Item = T>
147+
{
148+
self.item = iter.into_iter().fold(self.item, self.fold_op);
149+
self
150+
}
151+
144152
fn complete(self) -> C::Result {
145153
self.base.consume(self.item).complete()
146154
}

src/iter/inspect.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,14 @@ where
243243
}
244244
}
245245

246+
fn consume_iter<I>(mut self, iter: I) -> Self
247+
where
248+
I: IntoIterator<Item = T>
249+
{
250+
self.base = self.base.consume_iter(iter.into_iter().inspect(self.inspect_op));
251+
self
252+
}
253+
246254
fn complete(self) -> C::Result {
247255
self.base.complete()
248256
}

src/iter/map.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,14 @@ where
247247
}
248248
}
249249

250+
fn consume_iter<I>(mut self, iter: I) -> Self
251+
where
252+
I: IntoIterator<Item = T>,
253+
{
254+
self.base = self.base.consume_iter(iter.into_iter().map(self.map_op));
255+
self
256+
}
257+
250258
fn complete(self) -> C::Result {
251259
self.base.complete()
252260
}

src/iter/update.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,20 @@ where
245245
}
246246
}
247247

248+
fn consume_iter<I>(mut self, iter: I) -> Self
249+
where
250+
I: IntoIterator<Item = T>
251+
{
252+
let update_op = self.update_op;
253+
self.base = self.base.consume_iter(
254+
iter.into_iter().map(|mut item| {
255+
update_op(&mut item);
256+
item
257+
})
258+
);
259+
self
260+
}
261+
248262
fn complete(self) -> C::Result {
249263
self.base.complete()
250264
}

0 commit comments

Comments
 (0)