Rust 通过loop and push()或collect()创建一个包含顺序u64的大型Vec是否更快?
我正在寻找最有效的方法,因为我必须创建一个大约600000Rust 通过loop and push()或collect()创建一个包含顺序u64的大型Vec是否更快?,rust,Rust,我正在寻找最有效的方法,因为我必须创建一个大约600000u64整数的向量 这是我的第一次尝试: fn latest_ids(current_id: u64, latest_id: u64) -> Vec<u64> { let mut ids: Vec<u64> = vec![]; let mut start = current_id; while !(start >= latest_id) { start += 1;
u64
整数的向量
这是我的第一次尝试:
fn latest_ids(current_id: u64, latest_id: u64) -> Vec<u64> {
let mut ids: Vec<u64> = vec![];
let mut start = current_id;
while !(start >= latest_id) {
start += 1;
ids.push(start);
}
ids
}
fn最新\u id(当前\u id:u64,最新\u id:u64)->Vec{
让mut-id:Vec=Vec![];
让mut启动=当前\u id;
while!(开始>=最新的\u id){
开始+=1;
id.push(启动);
}
身份证
}
第二次尝试:
fn latest_ids(current_id: u64, latest_id: u64) -> Vec<u64> {
let ids: Vec<u64> = (current_id+1..latest_id).collect();
ids
}
fn最新\u id(当前\u id:u64,最新\u id:u64)->Vec{
let-id:Vec=(当前_-id+1..latest_-id).collect();
身份证
}
第二个版本更短/更干净,但我不确定
collect()
的效率如何?或者有更好的方法吗?如果您对防锈性能有任何疑问,请不要忘记
您可以看到,
collect
实际上比push
快很多。我猜这与push
有关,有时必须克隆整个Vec
,并将其移动到内存中的其他位置(不过请不要引用我的话)。您关于减速的推理是正确的。您可以使用vec::with_capacity(LATEST_ID-CURRENT_ID)
而不是vec,使推送版本更快(尽管可能仍然没有收集版本快)![]
@SebastianRedl这很有道理,但为什么收集速度要快得多呢?它有什么不同?@EvilRobotOverlord在范围迭代器上调用size\u hint
,因为迭代器确切地知道它有多少个元素,这允许vec精确地分配足够的空间并复制元素,而无需任何范围检查。虽然结论是正确的(AFAICT),但基准是不正确的。所创建的向量从未被使用过,因此编译器可以删除所有内容,从而导致0 ns的惊人时间(是的,在本例中没有,但仍然很危险)。在基准测试中,您必须始终确保使用或虚拟使用您的结果。正是出于这个目的,才有了test::black_box
。更好的是:您可以从iter()
中的闭包返回一个值,该值被放入一个黑框中。因此,只需从该闭包返回ids
,即可修复基准。@SebastianRedl另外,collect
可以使用memcpy
,具体取决于迭代器!(开始>=最新的\u id)
-为什么这么复杂?为什么不启动
?呜呜。。说得好。我错过了这个。注意:您可以将第二个版本简化为(当前\u id+1..latest\u id)。collect()
。不需要let
绑定。只需将collect()
表达式作为函数中的最后一个表达式即可。
#![feature(test)]
extern crate test;
#[cfg(test)]
mod tests {
use test::Bencher;
const CURRENT_ID: u64 = 1;
const LATEST_ID: u64 = 60000;
#[bench]
fn push(b: &mut Bencher) {
b.iter(|| {
let mut ids: Vec<u64> = vec![];
let mut start = CURRENT_ID;
while !(start >= LATEST_ID) {
start += 1;
ids.push(start);
}
});
}
#[bench]
fn collect(b: &mut Bencher) {
b.iter(|| {
let _ids: Vec<u64> = (CURRENT_ID + 1..LATEST_ID).collect();
});
}
}
running 2 tests
test tests::collect ... bench: 29,931 ns/iter (+/- 6,842)
test tests::push ... bench: 85,701 ns/iter (+/- 18,096)