No one ever said that safety was zero-cost. The article mentions bounds checks, but gives no measurements. Have they ever measured? Most data I've seen is that bounds checks cost less than 1% in real-world code. I will boldly assert that there has never been a product that couldn't be shipped because that 1% caused them to miss a performance goal. We could get into the weeds and go off on a tangent about linear algebra kernels and loop transformations being slower / more difficult with bounds checks, but that is an absolute niche case that can be solved with different techniques like loop versioning and static assertions.
Dropbox famously found bounds checks to be expensive in one part of their Rust code, so they introduced the equivalent of a feature flag to toggle them.
Related, the prominent Rust community member "Shnatsel" wrote an article [1] about exactly that in January. It's a great look at the problem, and gives some actual data to evaluate with.
[1]: https://shnatsel.medium.com/how-to-avoid-bounds-checks-in-ru...
E.g. the simplest case:
for (i = 0; i < some_expr; i++) {
a[i] = other_expr; // cannot prove is in bounds
}
Becomes: var t = some_expr;
if (t <= a.length) {
for (i = 0; i < t; i++) {
a[i] = other_expr; // no bounds check necessary
}
} else {
for (i = 0; i < a.length; i++) {
a[i] = other_expr; // no bounds check necessary
}
throw OutOfBoundsError; // throw exception at first OOB iteration
}
This approach will have exactly the same behavior as the original program and run without bounds checks in either case. It will even throw at the right time. The cost is having two copies of the loop and a check up-front. This specific case could be done with one version, and other cases can be done with a different partitioning of the loops.I feel people are lacking imagination on what an awesome buffet of compiler transforms are available when it is both absolutely required to do bounds checks and absolutely necessary to try to eliminate them everywhere. In practice, many many loops are trivially in bounds, many other loops are cold enough or big enough that the cost of a bounds check isn't much. You don't need to unroll and version every loop in the program. And like I said, for the loops outside of this set, where iterations are not affine or the indexes are irregular, you either live with bounds checks or you go deeper on allowing static assertions to prove accesses are in bounds. That's exactly the cases where you probably want checks anyway.
Yes.
>Most data I've seen is that bounds checks cost less than 1% in real-world code
So? I don't know where you got you data, but the point of the article is that you don't have to pay for the stuff you don't need. Otherwise we could as well use Java or VBA because "most data" says that programs spend 99% of time waiting on IO. If your data shows that then go ahead and use it, other people have other data apparently.
I kind of don't get this attitude, TBH. A bad register allocation decision could cost 5% in the wrong circumstance, yet no one is suggesting reintroducing the register keyword, and rarely do they drop down to asm to get it. But as soon as the cost is for "safety" they're hell-bent on getting rid of it. Wth.
5% of what?
>yet no one is suggesting reintroducing the register keyword
If I understood you, you mean that some variable might be allocated on stack instead of register and we need "register" keyword to alleviate this? Not really, when such thing happens we write asm() block which has all capabilities of the old register keyword and much more. And if 5% is latency then who in real time would not get to asm() to get it? This whole talk of "1% this, 5% that" seems just some kind of reddit meme. Would you give me 1% of your income for nothing? If not then why would you increase latency by 1%? Would you write five line of assembly to get 5% raise? If you would, then why would not you want to do it to drop latency by that much?