Replace push loops with extend() where possible#52738
Conversation
|
r? @eddyb (rust_highfive has picked a reviewer for you, use r? to override) |
|
Drive by comment, All these lovely clean up prs you have submitted... maybe we should suggest that clippy lint for them? So they can spread to the ecosystem? |
|
@Eh2406 clippy has an impressive set of working lints and some of them were a direct inspiration for some of my cleanups. I checked the ones that I haven't seen in clippy and it appears that they have already been proposed 😃: |
src/libsyntax/ast.rs
Outdated
There was a problem hiding this comment.
You can do this sort of thing by using .collect::<Result<Vec<_>, _>>() (for Result element types).
src/librustc/cfg/construct.rs
Outdated
There was a problem hiding this comment.
Can be collect instead (using iter::once for the first element above).
src/libstd/sys/redox/process.rs
Outdated
There was a problem hiding this comment.
Can be collect instead (with iter::once).
|
@eddyb great suggestions, applied. thanks! |
|
Rebased after 1bc49a9. |
There was a problem hiding this comment.
Pretty sure you need to collect this, and not hold that borrow_mut for that long, because the loop calls methods on self which could try to borrow again self.region_obligations. cc @nikomatsakis
There was a problem hiding this comment.
I wanted to collect this, but the borrowed value didn't live long enough.
There was a problem hiding this comment.
What did you write? I'm guessing it's just some scope thing.
There was a problem hiding this comment.
In general, let v = { let mut x = y.borrow_mut(); x.foo().collect() }; doesn't work, you need another variable inside the block, e.g. let v = { let mut x = y.borrow_mut(); let v = x.foo().collect(); v };
There was a problem hiding this comment.
Ah yeah, that should work; I'll fix this shortly.
src/libsyntax/ast.rs
Outdated
There was a problem hiding this comment.
Pretty sure this can also use collect (it's a lot like the code below).
|
@bors r+ |
|
📌 Commit 6071fb762a3add82a54307fbe79df83c5c9bdb85 has been approved by |
|
⌛ Testing commit 6071fb762a3add82a54307fbe79df83c5c9bdb85 with merge e7f363a2f3b01512e6ca1cdd569db506711f38a5... |
|
💔 Test failed - status-travis |
|
The job Click to expand the log.I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact |
|
Ah yes, Redox isn't |
|
@eddyb can you ask bors to retry? |
|
@bors r+ |
|
📌 Commit 59c8a27 has been approved by |
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.
|
☀️ Test successful - status-appveyor, status-travis |
…-Simulacrum Use Vec::extend in SmallVec::extend when applicable As calculated in rust-lang#52738, `Vec::extend` is much faster than `push`ing to it in a loop. We can take advantage of this method in `SmallVec` too - at least in cases when its underlying object is an `AccumulateVec::Heap`. ~~This approach also accidentally improves the `push` loop of the `AccumulateVec::Array` variant, because it doesn't utilize `SmallVec::push` which performs `self.reserve(1)` with every iteration; this is unnecessary, because we're already reserving the whole space we will be needing by performing `self.reserve(iter.size_hint().0)` at the beginning.~~
…-Simulacrum Use Vec::extend in SmallVec::extend when applicable As calculated in rust-lang#52738, `Vec::extend` is much faster than `push`ing to it in a loop. We can take advantage of this method in `SmallVec` too - at least in cases when its underlying object is an `AccumulateVec::Heap`. ~~This approach also accidentally improves the `push` loop of the `AccumulateVec::Array` variant, because it doesn't utilize `SmallVec::push` which performs `self.reserve(1)` with every iteration; this is unnecessary, because we're already reserving the whole space we will be needing by performing `self.reserve(iter.size_hint().0)` at the beginning.~~
Don't collect() when size_hint is useless This adjusts PRs rust-lang#52738 and rust-lang#52697 by falling back to calculating capacity and extending or pushing in a loop where `collect()` can't be trusted to calculate the right capacity. It is a performance win.
Don't collect() when size_hint is useless This adjusts PRs rust-lang#52738 and rust-lang#52697 by falling back to calculating capacity and extending or pushing in a loop where `collect()` can't be trusted to calculate the right capacity. It is a performance win.
Or set the vector capacity where I couldn't do it.
According to my simple benchmark
extending a vector can be over 10 times faster thanpushing to it in a loop:10 elements (6.1 times faster):
100 elements (11.12 times faster):
1000 elements (11.04 times faster):
Seems like a good idea to use
extendas much as possible.