Rust 通过loop and push()或collect()创建一个包含顺序u64的大型Vec是否更快?

Rust 通过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;

我正在寻找最有效的方法,因为我必须创建一个大约600000
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)