Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is the performance of `while` said to be slower than `for` when iterating over an array?

The second edition of The Rust Programming Language states the following about while loops for iterating over an array:

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

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

        index = index + 1;
    }
}

[...] It’s also slow, because the compiler adds runtime code to perform the conditional check on every element on every iteration through the loop.

As a more efficient alternative, you can use a for loop and execute some code for each item in a collection.

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

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

In C++ I would expect a compiler/optimizer to produce something with equivalent run-time performance.

Why is this not the case in Rust?

like image 861
Tobias Hermann Avatar asked Jul 23 '17 11:07

Tobias Hermann


1 Answers

In C++ I would expect a compiler/optimizer to produce something with equivalent run-time performance.

Because the two snippets are not equivalent. The use of a[i] in Rust maps to a.at(i) and the use of unsafe { a.get_unchecked(i) } in Rust maps to a[i] in C++.

That is, C++ does not perform bounds-checking by default, which is how you get buffer overflows.

Why is this not the case in Rust?

Rust, when not using the unsafe keyword, should be memory safe. In many situations this is achieved by compile-time checks, but bounds checking require runtime checks in general.

This does not mean that the while case will always be slower: it just means that you submit yourself to the whims of the optimizer, and sometimes it lets you down (eliminating bounds-checks is a hard problem).

Thus, the recommendation is to use idioms which are known to optimize well.

like image 100
Matthieu M. Avatar answered Nov 15 '22 05:11

Matthieu M.