4 ms·
C++ programs do not fail 30% of the time though. Safety concerns matter when the program is actively being attacked, the reason libjpeg had these bugs in the fi
by pandaman 3y ago
C++ programs do not fail 30% of the time though. Safety concerns matter when the program is actively being attacked, the reason libjpeg had these bugs in the first place was that it works just fine in absence of attacks so nobody bothered to find them. It would be nice if by switching to some magic language we've got safety at no cost but it's not the case in the reality.
- titzer 3y ago> we've got safety at no cost 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.
- pandaman 3y ago>Have they ever measured? 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.
- titzer 3y ago> the point of the article is that you don't have to pay for the stuff you don't need. 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.
- pandaman 3y ago> A bad register allocation decision could cost 5% in the wrong circumstance 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?
- steveklabnik 3y agoWhat is more important than "are bounds checks expensive or not" is that Rust gives you tools to do both, just like C++ gives you tools that do both. The defaults are flipped, but both languages are equally capable. 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.
- herbstein 3y ago> The article mentions bounds checks, but gives no measurements. Have they ever measured? 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-rust-without-unsafe-f65e618b4c1e https://shnatsel.medium.com/how-to-avoid-bounds-checks-in-ru...
- titzer 3y agoThanks for the reference. Several of the examples given could benefit from loop versioning and/or iteration space partitioning, i.e. the compiler splitting a loop that it cannot prove is always in-bounds to an in-bounds part and a possibly-out-of-bounds part. The HotSpot C2 compiler does this under some circumstances. 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.