Skip to content

Commit 866a713

Browse files
committed
Auto merge of #52738 - ljedrz:push_to_extend, r=eddyb
Replace push loops with extend() where possible Or set the vector capacity where I couldn't do it. According to my [simple benchmark](https://gist.github.com/ljedrz/568e97621b749849684c1da71c27dceb) `extend`ing a vector can be over **10 times** faster than `push`ing to it in a loop: 10 elements (6.1 times faster): ``` test bench_extension ... bench: 75 ns/iter (+/- 23) test bench_push_loop ... bench: 458 ns/iter (+/- 142) ``` 100 elements (11.12 times faster): ``` test bench_extension ... bench: 87 ns/iter (+/- 26) test bench_push_loop ... bench: 968 ns/iter (+/- 3,528) ``` 1000 elements (11.04 times faster): ``` test bench_extension ... bench: 311 ns/iter (+/- 9) test bench_push_loop ... bench: 3,436 ns/iter (+/- 233) ``` Seems like a good idea to use `extend` as much as possible.
2 parents 70cac59 + 59c8a27 commit 866a713

File tree

28 files changed

+101
-150
lines changed

28 files changed

+101
-150
lines changed

src/bootstrap/util.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -92,10 +92,7 @@ pub fn push_exe_path(mut buf: PathBuf, components: &[&str]) -> PathBuf {
9292
file.push_str(".exe");
9393
}
9494

95-
for c in components {
96-
buf.push(c);
97-
}
98-
95+
buf.extend(components);
9996
buf.push(file);
10097

10198
buf

src/librustc/cfg/construct.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -567,12 +567,12 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
567567
fn add_returning_edge(&mut self,
568568
_from_expr: &hir::Expr,
569569
from_index: CFGIndex) {
570-
let mut data = CFGEdgeData {
571-
exiting_scopes: vec![],
570+
let data = CFGEdgeData {
571+
exiting_scopes: self.loop_scopes.iter()
572+
.rev()
573+
.map(|&LoopScope { loop_id: id, .. }| id)
574+
.collect()
572575
};
573-
for &LoopScope { loop_id: id, .. } in self.loop_scopes.iter().rev() {
574-
data.exiting_scopes.push(id);
575-
}
576576
self.graph.add_edge(from_index, self.fn_exit, data);
577577
}
578578

src/librustc/infer/outlives/obligations.rs

+5-6
Original file line numberDiff line numberDiff line change
@@ -151,13 +151,12 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
151151
debug!("process_registered_region_obligations()");
152152

153153
// pull out the region obligations with the given `body_id` (leaving the rest)
154-
let mut my_region_obligations = Vec::with_capacity(self.region_obligations.borrow().len());
155-
{
154+
let my_region_obligations = {
156155
let mut r_o = self.region_obligations.borrow_mut();
157-
for (_, obligation) in r_o.drain_filter(|(ro_body_id, _)| *ro_body_id == body_id) {
158-
my_region_obligations.push(obligation);
159-
}
160-
}
156+
let my_r_o = r_o.drain_filter(|(ro_body_id, _)| *ro_body_id == body_id)
157+
.map(|(_, obligation)| obligation).collect::<Vec<_>>();
158+
my_r_o
159+
};
161160

162161
let outlives = &mut TypeOutlives::new(
163162
self,

src/librustc/middle/reachable.rs

+2-6
Original file line numberDiff line numberDiff line change
@@ -367,9 +367,7 @@ impl<'a, 'tcx: 'a> ItemLikeVisitor<'tcx> for CollectPrivateImplItemsVisitor<'a,
367367
// We need only trait impls here, not inherent impls, and only non-exported ones
368368
if let hir::ItemKind::Impl(.., Some(ref trait_ref), _, ref impl_item_refs) = item.node {
369369
if !self.access_levels.is_reachable(item.id) {
370-
for impl_item_ref in impl_item_refs {
371-
self.worklist.push(impl_item_ref.id.node_id);
372-
}
370+
self.worklist.extend(impl_item_refs.iter().map(|r| r.id.node_id));
373371

374372
let trait_def_id = match trait_ref.path.def {
375373
Def::Trait(def_id) => def_id,
@@ -426,9 +424,7 @@ fn reachable_set<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, crate_num: CrateNum) ->
426424
// If other crates link to us, they're going to expect to be able to
427425
// use the lang items, so we need to be sure to mark them as
428426
// exported.
429-
for (id, _) in &access_levels.map {
430-
reachable_context.worklist.push(*id);
431-
}
427+
reachable_context.worklist.extend(access_levels.map.iter().map(|(id, _)| *id));
432428
for item in tcx.lang_items().items().iter() {
433429
if let Some(did) = *item {
434430
if let Some(node_id) = tcx.hir.as_local_node_id(did) {

src/librustc/mir/traversal.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,7 @@ impl<'a, 'tcx> Iterator for Preorder<'a, 'tcx> {
6464
let data = &self.mir[idx];
6565

6666
if let Some(ref term) = data.terminator {
67-
for &succ in term.successors() {
68-
self.worklist.push(succ);
69-
}
67+
self.worklist.extend(term.successors());
7068
}
7169

7270
return Some((idx, data));

src/librustc/session/config.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -899,9 +899,7 @@ macro_rules! options {
899899
-> bool {
900900
match v {
901901
Some(s) => {
902-
for s in s.split_whitespace() {
903-
slot.push(s.to_string());
904-
}
902+
slot.extend(s.split_whitespace().map(|s| s.to_string()));
905903
true
906904
},
907905
None => false,

src/librustc/traits/specialize/mod.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -438,9 +438,9 @@ fn to_pretty_impl_header(tcx: TyCtxt, impl_def_id: DefId) -> Option<String> {
438438
}
439439
pretty_predicates.push(p.to_string());
440440
}
441-
for ty in types_without_default_bounds {
442-
pretty_predicates.push(format!("{}: ?Sized", ty));
443-
}
441+
pretty_predicates.extend(
442+
types_without_default_bounds.iter().map(|ty| format!("{}: ?Sized", ty))
443+
);
444444
if !pretty_predicates.is_empty() {
445445
write!(w, "\n where {}", pretty_predicates.join(", ")).unwrap();
446446
}

src/librustc_codegen_llvm/back/rpath.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -152,9 +152,7 @@ fn path_relative_from(path: &Path, base: &Path) -> Option<PathBuf> {
152152
(Some(_), Some(b)) if b == Component::ParentDir => return None,
153153
(Some(a), Some(_)) => {
154154
comps.push(Component::ParentDir);
155-
for _ in itb {
156-
comps.push(Component::ParentDir);
157-
}
155+
comps.extend(itb.map(|_| Component::ParentDir));
158156
comps.push(a);
159157
comps.extend(ita.by_ref());
160158
break;

src/librustc_codegen_llvm/debuginfo/metadata.rs

+11-12
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ use rustc::util::common::path2cstr;
3939
use libc::{c_uint, c_longlong};
4040
use std::ffi::CString;
4141
use std::fmt::Write;
42+
use std::iter;
4243
use std::ptr;
4344
use std::path::{Path, PathBuf};
4445
use syntax::ast;
@@ -364,18 +365,16 @@ fn subroutine_type_metadata<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
364365
&signature,
365366
);
366367

367-
let mut signature_metadata: Vec<DIType> = Vec::with_capacity(signature.inputs().len() + 1);
368-
369-
// return type
370-
signature_metadata.push(match signature.output().sty {
371-
ty::TyTuple(ref tys) if tys.is_empty() => ptr::null_mut(),
372-
_ => type_metadata(cx, signature.output(), span)
373-
});
374-
375-
// regular arguments
376-
for &argument_type in signature.inputs() {
377-
signature_metadata.push(type_metadata(cx, argument_type, span));
378-
}
368+
let signature_metadata: Vec<DIType> = iter::once(
369+
// return type
370+
match signature.output().sty {
371+
ty::TyTuple(ref tys) if tys.is_empty() => ptr::null_mut(),
372+
_ => type_metadata(cx, signature.output(), span)
373+
}
374+
).chain(
375+
// regular arguments
376+
signature.inputs().iter().map(|argument_type| type_metadata(cx, argument_type, span))
377+
).collect();
379378

380379
return_if_metadata_created_in_meantime!(cx, unique_type_id);
381380

src/librustc_codegen_llvm/debuginfo/mod.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -352,9 +352,10 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CodegenCx<'a, 'tcx>,
352352

353353
if sig.abi == Abi::RustCall && !sig.inputs().is_empty() {
354354
if let ty::TyTuple(args) = sig.inputs()[sig.inputs().len() - 1].sty {
355-
for &argument_type in args {
356-
signature.push(type_metadata(cx, argument_type, syntax_pos::DUMMY_SP));
357-
}
355+
signature.extend(
356+
args.iter().map(|argument_type|
357+
type_metadata(cx, argument_type, syntax_pos::DUMMY_SP))
358+
);
358359
}
359360
}
360361

src/librustc_driver/lib.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -1588,10 +1588,7 @@ pub fn in_rustc_thread<F, R>(f: F) -> Result<R, Box<dyn Any + Send>>
15881588
/// debugging, since some ICEs only happens with non-default compiler flags
15891589
/// (and the users don't always report them).
15901590
fn extra_compiler_flags() -> Option<(Vec<String>, bool)> {
1591-
let mut args = Vec::new();
1592-
for arg in env::args_os() {
1593-
args.push(arg.to_string_lossy().to_string());
1594-
}
1591+
let args = env::args_os().map(|arg| arg.to_string_lossy().to_string()).collect::<Vec<_>>();
15951592

15961593
// Avoid printing help because of empty args. This can suggest the compiler
15971594
// itself is not the program root (consider RLS).

src/librustc_driver/profile/trace.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -204,10 +204,9 @@ pub fn write_counts(count_file: &mut File, counts: &mut HashMap<String,QueryMetr
204204
use rustc::util::common::duration_to_secs_str;
205205
use std::cmp::Reverse;
206206

207-
let mut data = vec![];
208-
for (ref cons, ref qm) in counts.iter() {
209-
data.push((cons.clone(), qm.count.clone(), qm.dur_total.clone(), qm.dur_self.clone()));
210-
};
207+
let mut data = counts.iter().map(|(ref cons, ref qm)|
208+
(cons.clone(), qm.count.clone(), qm.dur_total.clone(), qm.dur_self.clone())
209+
).collect::<Vec<_>>();
211210
data.sort_by_key(|k| Reverse(k.3));
212211
for (cons, count, dur_total, dur_self) in data {
213212
write!(count_file, "{}, {}, {}, {}\n",

src/librustc_llvm/lib.rs

+1-5
Original file line numberDiff line numberDiff line change
@@ -275,12 +275,8 @@ pub fn get_param(llfn: ValueRef, index: c_uint) -> ValueRef {
275275
fn get_params(llfn: ValueRef) -> Vec<ValueRef> {
276276
unsafe {
277277
let num_params = LLVMCountParams(llfn);
278-
let mut params = Vec::with_capacity(num_params as usize);
279-
for idx in 0..num_params {
280-
params.push(LLVMGetParam(llfn, idx));
281-
}
282278

283-
params
279+
(0..num_params).map(|idx| LLVMGetParam(llfn, idx)).collect()
284280
}
285281
}
286282

src/librustc_mir/transform/inline.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -406,10 +406,9 @@ impl<'a, 'tcx> Inliner<'a, 'tcx> {
406406
local_map.push(idx);
407407
}
408408

409-
for p in callee_mir.promoted.iter().cloned() {
410-
let idx = caller_mir.promoted.push(p);
411-
promoted_map.push(idx);
412-
}
409+
promoted_map.extend(
410+
callee_mir.promoted.iter().cloned().map(|p| caller_mir.promoted.push(p))
411+
);
413412

414413
// If the call is something like `a[*i] = f(i)`, where
415414
// `i : &mut usize`, then just duplicating the `a[*i]`

src/librustc_resolve/lib.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -3831,9 +3831,9 @@ impl<'a> Resolver<'a> {
38313831
}
38323832
// Add primitive types to the mix
38333833
if filter_fn(Def::PrimTy(TyBool)) {
3834-
for (name, _) in &self.primitive_type_table.primitive_types {
3835-
names.push(*name);
3836-
}
3834+
names.extend(
3835+
self.primitive_type_table.primitive_types.iter().map(|(name, _)| name)
3836+
)
38373837
}
38383838
} else {
38393839
// Search in module.

src/librustc_save_analysis/dump_visitor.rs

+5-6
Original file line numberDiff line numberDiff line change
@@ -1318,14 +1318,13 @@ impl<'l, 'tcx: 'l, 'll, O: DumpOutput + 'll> DumpVisitor<'l, 'tcx, 'll, O> {
13181318
};
13191319

13201320
// Make a comma-separated list of names of imported modules.
1321-
let mut names = vec![];
13221321
let glob_map = &self.save_ctxt.analysis.glob_map;
13231322
let glob_map = glob_map.as_ref().unwrap();
1324-
if glob_map.contains_key(&id) {
1325-
for n in glob_map.get(&id).unwrap() {
1326-
names.push(n.to_string());
1327-
}
1328-
}
1323+
let names = if glob_map.contains_key(&id) {
1324+
glob_map.get(&id).unwrap().iter().map(|n| n.to_string()).collect()
1325+
} else {
1326+
Vec::new()
1327+
};
13291328

13301329
let sub_span = self.span.sub_span_of_token(use_tree.span,
13311330
token::BinOp(token::Star));

src/librustc_typeck/collect.rs

+16-17
Original file line numberDiff line numberDiff line change
@@ -962,19 +962,21 @@ fn generics_of<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
962962
&["<closure_kind>", "<closure_signature>"][..]
963963
};
964964

965-
for (i, &arg) in dummy_args.iter().enumerate() {
966-
params.push(ty::GenericParamDef {
967-
index: type_start + i as u32,
968-
name: Symbol::intern(arg).as_interned_str(),
969-
def_id,
970-
pure_wrt_drop: false,
971-
kind: ty::GenericParamDefKind::Type {
972-
has_default: false,
973-
object_lifetime_default: rl::Set1::Empty,
974-
synthetic: None,
975-
},
976-
});
977-
}
965+
params.extend(
966+
dummy_args.iter().enumerate().map(|(i, &arg)|
967+
ty::GenericParamDef {
968+
index: type_start + i as u32,
969+
name: Symbol::intern(arg).as_interned_str(),
970+
def_id,
971+
pure_wrt_drop: false,
972+
kind: ty::GenericParamDefKind::Type {
973+
has_default: false,
974+
object_lifetime_default: rl::Set1::Empty,
975+
synthetic: None,
976+
},
977+
}
978+
)
979+
);
978980

979981
tcx.with_freevars(node_id, |fv| {
980982
params.extend(fv.iter().zip((dummy_args.len() as u32)..).map(|(_, i)| {
@@ -1651,10 +1653,7 @@ fn explicit_predicates_of<'a, 'tcx>(
16511653
&mut projections);
16521654

16531655
predicates.push(trait_ref.to_predicate());
1654-
1655-
for projection in &projections {
1656-
predicates.push(projection.to_predicate());
1657-
}
1656+
predicates.extend(projections.iter().map(|p| p.to_predicate()));
16581657
}
16591658

16601659
&hir::GenericBound::Outlives(ref lifetime) => {

src/librustdoc/core.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -203,9 +203,7 @@ pub fn run_core(search_paths: SearchPaths,
203203
intra_link_resolution_failure_name.to_owned(),
204204
missing_docs.to_owned()];
205205

206-
for (lint, _) in &cmd_lints {
207-
whitelisted_lints.push(lint.clone());
208-
}
206+
whitelisted_lints.extend(cmd_lints.iter().map(|(lint, _)| lint).cloned());
209207

210208
let lints = lint::builtin::HardwiredLints.get_lints()
211209
.into_iter()

src/librustdoc/lib.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -722,9 +722,7 @@ where R: 'static + Send,
722722
},
723723
_ => continue,
724724
};
725-
for p in value.as_str().split_whitespace() {
726-
sink.push(p.to_string());
727-
}
725+
sink.extend(value.as_str().split_whitespace().map(|p| p.to_string()));
728726
}
729727

730728
if attr.is_word() && name == Some("document_private_items") {

src/libserialize/json.rs

+3-9
Original file line numberDiff line numberDiff line change
@@ -1364,9 +1364,7 @@ impl Stack {
13641364
// Used by Parser to insert StackElement::Key elements at the top of the stack.
13651365
fn push_key(&mut self, key: string::String) {
13661366
self.stack.push(InternalKey(self.str_buffer.len() as u16, key.len() as u16));
1367-
for c in key.as_bytes() {
1368-
self.str_buffer.push(*c);
1369-
}
1367+
self.str_buffer.extend(key.as_bytes());
13701368
}
13711369

13721370
// Used by Parser to insert StackElement::Index elements at the top of the stack.
@@ -2212,9 +2210,7 @@ impl ::Decoder for Decoder {
22122210
};
22132211
match o.remove(&"fields".to_string()) {
22142212
Some(Json::Array(l)) => {
2215-
for field in l.into_iter().rev() {
2216-
self.stack.push(field);
2217-
}
2213+
self.stack.extend(l.into_iter().rev());
22182214
},
22192215
Some(val) => {
22202216
return Err(ExpectedError("Array".to_owned(), val.to_string()))
@@ -2346,9 +2342,7 @@ impl ::Decoder for Decoder {
23462342
{
23472343
let array = expect!(self.pop(), Array)?;
23482344
let len = array.len();
2349-
for v in array.into_iter().rev() {
2350-
self.stack.push(v);
2351-
}
2345+
self.stack.extend(array.into_iter().rev());
23522346
f(self, len)
23532347
}
23542348

src/libstd/sys/redox/process.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use ffi::OsStr;
1313
use os::unix::ffi::OsStrExt;
1414
use fmt;
1515
use io::{self, Error, ErrorKind};
16+
use iter;
1617
use libc::{EXIT_SUCCESS, EXIT_FAILURE};
1718
use path::{Path, PathBuf};
1819
use sys::fd::FileDesc;
@@ -296,11 +297,11 @@ impl Command {
296297
t!(callback());
297298
}
298299

299-
let mut args: Vec<[usize; 2]> = Vec::new();
300-
args.push([self.program.as_ptr() as usize, self.program.len()]);
301-
for arg in self.args.iter() {
302-
args.push([arg.as_ptr() as usize, arg.len()]);
303-
}
300+
let args: Vec<[usize; 2]> = iter::once(
301+
[self.program.as_ptr() as usize, self.program.len()]
302+
).chain(
303+
self.args.iter().map(|arg| [arg.as_ptr() as usize, arg.len()])
304+
).collect();
304305

305306
self.env.apply();
306307

0 commit comments

Comments
 (0)