-
Notifications
You must be signed in to change notification settings - Fork 13k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
libcollections: move Vec::push slow path out #23670
Conversation
r? @aturon (rust_highfive has picked a reviewer for you, use r? to override) |
r? @pcwalton |
Vec already has a resize fn |
See also the private grow_capacity method for some pre-existing refactoring of this functionality. |
@gankro using |
Makes Vec::push considerably smaller: 25 instructions, rather than 42, on x86_64.
Yeah, new version works the same. |
Do you happen to have some before/after benchmarks? |
@cmr I was moreso suggesting there might be a better refactoring to reduce duplication, but this certainly doesn't make it worse. |
@huonw No, but I could fabricate one that is predicated on icache residency. |
(@erickt also mentioned wanting this in serde) |
I would personally also prefer to see at least one benchmark showing one way or another here. This is unfortunately a loss in readability in the code and is an idiom we only rarely apply today, so I would prefer to have some numbers backing it up showing why the loss in readability is worth it. |
Smaller function size is the main goal (this makes push 40% smaller), which can help inlining in complex functions and reduce icache pressure. Here's one silly benchmark: extern crate test;
#[bench]
fn x(b: &mut test::Bencher) {
let mut v = Vec::with_capacity(100);
b.iter(|| { v.extend(0..100); v.truncate(0); });
}
|
For reference, against the C++ equivalent: #include <vector>
#include <cstdint>
extern "C" {
void cpp_version() {
static std::vector<int32_t> v(100);
for (int i = 0; i < 100; i++) {
v.push_back(i);
}
v.resize(0);
}
} extern crate test;
#[bench]
fn x(b: &mut test::Bencher) {
let mut v = Vec::with_capacity(100);
b.iter(|| { v.extend(0..100); v.truncate(0); });
}
#[link(name = "foo")]
#[link(name = "stdc++")]
extern "C" {
fn cpp_version();
}
#[bench]
fn cpp(b: &mut test::Bencher) {
b.iter(|| unsafe { cpp_version() });
}
Maybe framing it as "Make Vec::push faster than C++ vector::push_back" makes it go down better ;) |
@bors: r=pcwalton rollup |
📌 Commit 0e838f7 has been approved by |
⌛ Testing commit 0e838f7 with merge 928e2e2... |
Makes Vec::push considerably smaller: 25 instructions, rather than 42, on x86_64.
Makes Vec::push considerably smaller: 25 instructions, rather than 42, on
x86_64.