简体   繁体   English

为什么Rust文档说数组的while循环比for循环慢?

[英]Why does the Rust documentation say that a while loop over an array is slower than a for loop?

As I was reading the rust documentation, I stumbled upon this code that iterates the array a using a while loop (with an index): 正如我正在读锈文档,我偶然发现此代码 ,遍历该阵列a使用一个while循环(具有索引):

fn main() {
    let a = [10, 20, 30, 40, 50];
    let mut index = 0;

    while index < 5 {
        println!("the value is: {}", a[index]);

        index += 1;
    }
}

The documentation says: 该文件说:

... this approach is error prone; ...这种方法容易出错; we could cause the program to panic if the index length is incorrect. 如果索引长度不正确,我们可能会导致程序崩溃。 It's also slow, because the compiler adds runtime code to perform the conditional check on every element on every iteration through the loop. 这也很慢,因为编译器添加了运行时代码,以对循环中每次迭代的每个元素执行条件检查。

The first reason was self-explanatory. 第一个原因是不言自明的。 The second reason was where I got confused. 第二个原因是我感到困惑。

Furthermore, they suggested to use a for-loop for this. 此外,他们建议为此使用for循环。

fn main() {
    let a = [10, 20, 30, 40, 50];

    for element in a.iter() {
        println!("the value is: {}", element);
    }
}

I just can't seem to wrap my head around this. 我似乎无法解决这个问题。 Is there some kind of behavior that the Rust compiler does? Rust编译器有某种行为吗?

The two parts are complementary: 这两个部分是互补的:

we could cause the program to panic if the index length is incorrect. 如果索引长度不正确,我们可能会导致程序崩溃。

Every time you write some_slice[some_index] , the standard library does the equivalent of: 每次您编写some_slice[some_index] ,标准库都会执行以下操作:

if some_index < some_slice.len() {
    some_slice.get_the_value_without_checks(some_index)
} else {
    panic!("Hey, stop that");
}

the compiler adds runtime code to perform the conditional check on every element 编译器添加运行时代码以对每个元素执行条件检查

In a loop, this works out to be something like: 在一个循环中,结果类似于:

while some_index < limit {
    if some_index < some_slice.len() {
        some_slice.get_the_value_without_checks(some_index)
    } else {
        panic!("Hey, stop that");
    }
    some_index += 1;
}

Those repeated conditionals aren't the most efficient code. 这些重复的条件并不是最有效的代码。

The implementations of Iterator for slices utilize unsafe code to be more efficient at the expense of more complicated code. 切片的Iterator的实现利用unsafe代码来提高效率,但以更复杂的代码为代价。 The iterators contain raw pointers to the data but ensure that you can never misuse them to cause memory unsafety. 迭代器包含指向数据的原始指针,但要确保您永远不会滥用它们以导致内存不安全。 Without needing to perform that conditional at each step, the iterator solution is often faster 1 . 不需要在每个步骤都执行该条件,迭代器解决方案通常会更快1 It's more-or-less equivalent to: 它差不多等于:

while some_index < limit {
    some_slice.get_the_value_without_checks(some_index)
    some_index += 1;
}

See also: 也可以看看:


1 — as Matthieu M. points out : 1-正如Matthieu M.指出的

It should be noted that the optimizer may (or may not) be able to remove the bounds check in the while case. 应该注意的是,在while情况下,优化器可能(也可能无法)删除边界检查。 If it succeeds, then performance is equivalent; 如果成功,则性能是等​​效的。 if it fails, suddenly your code is slower. 如果失败,您的代码突然变慢。 In microbenchmarks, with simple code, changes are it will succeed... but this may not carry to your production code, or it may carry now, and the next change in the loop body will prevent the optimization, etc... In short, a while loop can be a performance ticking bomb. 在微基准测试中,使用简单的代码,更改是否会成功……但是,这可能不会带到您的生产代码中,或者可能会立即生效,并且循环体中的下一个更改将阻止优化,等等。 , while循环可能是性能的炸弹。

See also: 也可以看看:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM