Live data from Hacker News

How much does Rust's bounds checking cost?

blog.readyset.io

81–90 of 195 posts

Re: How much does Rust's bounds checking cost?

#81

I've been shocked when I've heard C programmers being actually concerned about performance penalty of checks like, why bother? CPUs in next 2 years will win that performance anyway and your software will be safer

For proper bounds checking in C you first need to communicate the "bounds" to be "checked" to all the places where it matters, just a pointer isn't enough. Unfortunately many old-school C APIs (including the stdlib) often don't pass pointer-size pairs around, but just pointers (and IMHO the biggest problem in the C world is not so much the language, but outdated APIs like the C stdlib or POSIX which have mostly been designed in the K&R era and which basically "encourage" unsafe usage).

Other then that, I doubt that any reasonably pragmatic and experienced C programmer will ever argue against runtime bounds checking from a performance point of view. Even in hot loops one can usually move the bounds checking to a place outside the loop.

Re: How much does Rust's bounds checking cost?

#82

Earlier quoted context omitted.

I think we're suffering from some fuzziness about what bounds checks we're referring to. Even in your example, you only need to check the size of the Vec when you instantiate the iterator, not each time the iterator accesses an element, because at the time the iterator over the Vec 's contents is instantiated, the Vec 's size is known, and it can't change over the life of the iterator (because mutation is disallowed…

When I read "iterator" I think of an object that points into the vector and can be advanced. For Rust's vector, that is std::slice::Iter ( https://doc.rust-lang.org/std/slice/struct.Iter.html ). When you advance an iterator, you must do a bounds check if the vector is dynamically sized; otherwise, you don't know when to stop. I.e., if I have let mut it = vec.iter(); println!(it.next()); println!(it.next()); println!(…

The Rust docs for the 'for' keyword do say for loops are implemented as sugar for iterator loops. https://doc.rust-lang.org/std/keyword.for.html

Relevant part: > for-in-loops, or to be more precise, iterator loops, are a simple syntactic sugar over a common practice within Rust, which is to loop over anything that implements IntoIterator until the iterator returned by .into_iter() returns None (or the loop body uses break).

(The other uses of the 'for' keyword it refers to are unrelated to loops)

Re: How much does Rust's bounds checking cost?

#83
post #66

One technique is to add asserts before a block of code to hoist the checks out. The compiler is usually smart enough to know which conditions have already been checked. Here's a simple example: https://rust.godbolt.org/z/GPMcYd371 This can make a big difference if you can hoist bounds checks out of an inner loop. You get the performance without adding any unsafe {}.

Funnily there is an off-by-one error in your example; if you fix it, the generated assembly is even more efficient.

Re: How much does Rust's bounds checking cost?

#84
One thing that I assume reduces this problem even further is the prevalent use of iterators in Rust. I almost never index an array or vector directly, which means it's impossible for me to use an out of bounds index, and I'd be really surprised if rustc and/or LLVM don't somehow take advantage of that fact (maybe just through unchecked indexing in the standard library's iterator functions)

Re: How much does Rust's bounds checking cost?

#85
Back in the 80's, I was programming in Fortran on a VAX 780. I had converted a complex eigenvalue-eigenvector routine from Algol to Fortran, and, after verifying that it worked, decided to see how much bounds checking added to the runtime. I figured since so much array referencing was done that this would be a worst case scenario. In that particular situation, it added about 30%. I decided that this was well worth it and kept array bounds checking on in all my code.

Re: How much does Rust's bounds checking cost?

#86
post #69
post #66

One technique is to add asserts before a block of code to hoist the checks out. The compiler is usually smart enough to know which conditions have already been checked. Here's a simple example: https://rust.godbolt.org/z/GPMcYd371 This can make a big difference if you can hoist bounds checks out of an inner loop. You get the performance without adding any unsafe {}.

Yeah this is because the error message printed contains the location of the error as well as the attempted index. Thus, there are differences between the bounds failures and the optimizer can't hoist the check out (plus probably some concerns due to side effects of opaque functions).

I wonder if there could be a flag to tell the compiler that you don't care about getting the exact distinct panic message for each bounds check, please optimize it. I suppose the assert is a flag, in a way, but I mean something more global and automatic. Maybe the compiler could emit a single shared basic block per function that just says "out of bounds access in function foo".

We've learned to accept that when you turn on optimizations, you lose some lines and variables from your debug info. This is a pretty similar trade-off.

Re: How much does Rust's bounds checking cost?

#87
post #83
post #66

One technique is to add asserts before a block of code to hoist the checks out. The compiler is usually smart enough to know which conditions have already been checked. Here's a simple example: https://rust.godbolt.org/z/GPMcYd371 This can make a big difference if you can hoist bounds checks out of an inner loop. You get the performance without adding any unsafe {}.

Funnily there is an off-by-one error in your example; if you fix it, the generated assembly is even more efficient.

Hah! There's one reason not to switch everything to `unsafe get_unchecked()`.

Re: How much does Rust's bounds checking cost?

#88
post #4

A consistent 5 ms difference in micro-benchmarks is definitely not "measurement noise". Noise averages out way before accumulating to 5ms. There must be a reason and it mostly likely relates to the change. So you can confidently say that removing bounds checking (at least with how you did it) is a regression. ... that being said, I'd argue that the most beneficial memory-safety feature of Rust is about temporal thing…

It could be noise in a benchmark that does IO, or has determinism problems.

Re: How much does Rust's bounds checking cost?

#89

I've been shocked when I've heard C programmers being actually concerned about performance penalty of checks like, why bother? CPUs in next 2 years will win that performance anyway and your software will be safer

Single threaded perf gains have slowed down, this isn’t true anymore.

Re: How much does Rust's bounds checking cost?

#90
post #65

For Virgil, there is a switch to turn off bounds checking, for the only reason to measure their cost. (It's not expected that anyone ever do this for production code). Bounds checks do not appear to slow down any program that matters (TM) by more than 2%. That's partly because so many loops automatically have bounds checks removed by analysis. But still. It's negligible.

A 2% efficiency difference is tens if not hundreds of millions of dollars for Google, Meta, etc. Globally it’s enormous.
Post reply on HN