-
Notifications
You must be signed in to change notification settings - Fork 13.6k
Closed
Closed
Copy link
Labels
A-codegenArea: Code generationArea: Code generationA-collectionsArea: `std::collections`Area: `std::collections`A-iteratorsArea: IteratorsArea: IteratorsC-bugCategory: This is a bug.Category: This is a bug.I-slowIssue: Problems and improvements with respect to performance of generated code.Issue: Problems and improvements with respect to performance of generated code.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.T-libsRelevant to the library team, which will review and decide on the PR/issue.Relevant to the library team, which will review and decide on the PR/issue.
Description
I noticed today that using Vec::retain
is much slower than filtering and allocating a new Vector.
I realize the former is probably more memory efficient, but I still found it surprising that it would be that much slower (or really slower at all).
When testing with this code:
#![feature(test)]
extern crate test;
fn main() {
let xs: Vec<i32> = (0..1000).collect();
assert_eq!(even_with_retain(xs.clone()), even_with_filter(xs.clone()));
}
pub fn even_with_retain(mut xs: Vec<i32>) -> Vec<i32> {
xs.retain(|x| x & 1 == 0);
xs
}
pub fn even_with_filter(xs: Vec<i32>) -> Vec<i32> {
xs.into_iter().filter(|x| x & 1 == 0).collect()
}
#[bench]
fn bench_retain(b: &mut test::Bencher) {
let xs: Vec<i32> = (0..1000).collect();
b.iter(|| assert_eq!(even_with_retain(test::black_box(xs.clone())).len(), 500));
}
#[bench]
fn bench_filter_collect(b: &mut test::Bencher) {
let xs: Vec<i32> = (0..1000).collect();
b.iter(|| assert_eq!(even_with_filter(test::black_box(xs.clone())).len(), 500));
}
on 1.59.0-nightly (48a5999 2021-12-01), I get these benchmark results:
test bench_filter_collect ... bench: 383 ns/iter (+/- 4)
test bench_retain ... bench: 1,891 ns/iter (+/- 17)
on a Ryzen 5900X running Linux. Testing on a different machine (Xeon E3-1271 v3), I get similar numbers:
test bench_filter_collect ... bench: 498 ns/iter (+/- 29)
test bench_retain ... bench: 1,800 ns/iter (+/- 44)
Vec::retain
seemed like the obvious choice to me, so it being slower is either a bug or should be documented somewhere.
BluBb-mADe, funbringer, hkratz, Xuanwo, Kobzol and 4 more
Metadata
Metadata
Assignees
Labels
A-codegenArea: Code generationArea: Code generationA-collectionsArea: `std::collections`Area: `std::collections`A-iteratorsArea: IteratorsArea: IteratorsC-bugCategory: This is a bug.Category: This is a bug.I-slowIssue: Problems and improvements with respect to performance of generated code.Issue: Problems and improvements with respect to performance of generated code.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the compiler team, which will review and decide on the PR/issue.T-libsRelevant to the library team, which will review and decide on the PR/issue.Relevant to the library team, which will review and decide on the PR/issue.