7 ms·
You can do any rust optimization yourself in C++ (ie. aliasing assumptions), whereas rust makes the other way around very difficult, often forcing you to use mu
by alphanullmeric 3y ago
You can do any rust optimization yourself in C++ (ie. aliasing assumptions), whereas rust makes the other way around very difficult, often forcing you to use multiple layers of indirection where c++ would allow a raw pointer, or forcing an unwrap on something you know is infallible when exceptions would add no overhead, etc. Rust programmers want people to believe that whatever appeases the supposedly zero cost borrow checker is the fastest thing to do even though it has proven to be wrong time and time again. I can’t tell you how many times I’ve seen r/rust pull the “well why do you want to do that” or “are you sure it even matters” card every time rust doesn’t allow you to write optimized code.
- cortesoft 3y agoIsn't that the point of unsafe blocks in rust? So you can write optimized code when you need to and the rust borrow checker won't let you?
- gmueckl 3y agoUnsafe blocks are subject to the same borrow checking that the rest of the language is.
- tialaramex 3y agoThat is correct. However, raw pointers are not borrow checked, in safe Rust they're largely useless, but in unsafe Rust you can use raw pointers if that's what you need to do to get stuff done. As an example inside a String is just a Vec<u8> and inside the Vec<u8> is a RawVec<u8> and that is just a pointer, either to nothing in particular or to the bytes inside the String if the String has allocated space for one or more bytes - plus a size and a capacity.
- celeritascelery 3y ago> You can do any rust optimization yourself in C++ (ie. aliasing assumptions) I don’t think that is entirely true. C++ doesn’t have any aliasing requirements around pointers, so if the compiler sees two pointers it has to assume they might alias (unless the block is so simple it can determine aliasing itself, which is usually not the case), but in Rust mutable references are guaranteed to not alias. This was part of the reason it took so long to land the “noalias” LLVM attribute in Rust. That optimization was rarely used in C/C++ land so it had not been battle tested. Rust found a host of LLVM bugs because it enables the optimization everywhere.
- LegionMammal978 3y agoWhile standard C++ has no equivalent of a noalias annotation, it's wrong to say that it has no aliasing requirements. To access an object behind a pointer (or a glvalue in general), the type of the pointer must be (with a few exceptions) similar to the type of the pointee in memory, which is generally the object previously initialized at that pointer's address. This enables type-based alias analysis (TBAA) in the compiler, where if a pointer is accessed as one type, and another pointer is accessed as a dissimilar type, then the compiler can assume that the pointers don't alias. Meanwhile, Rust ditches TBAA entirely, retaining only initialization state and pointer provenance in its memory model. It uses its noalias-based model to make up for the lack of type-based rules. I'd say that this is the right call from the user's standpoint, but it can definitely be seen as a tradeoff rather than an unqualified gain.
- celeritascelery 3y agoWhy couldn’t the Rust compiler also assume that dissimilar types don’t alias?
- LegionMammal978 3y agoBecause existing unsafe code written in stable Rust depends on the ability to convert raw pointers and references from one type to another, as long as their memory layouts match. That's the whole premise of the bytemuck crate [0], and it's the basis for things like the &str-to-&[u8] or &[u8]-to-&str conversions in the standard library. [0] https://docs.rs/bytemuck/latest/bytemuck/ https://docs.rs/bytemuck/latest/bytemuck/
- thedracle 3y ago> when exceptions would add no overhead Isn't the overhead for C++ exceptions quite significant, especially if an exception is thrown? Exception handling can also increase the size of the binary because of the additional data needed to handle stack unwinding and exception dispatch. I think a number of optimizations are made quite a bit more complex by exception handling as well.
- tialaramex 3y agoThe argument for the Exception price is that we told you Exceptions were for Exceptional situations. This argument feels reasonable until you see it in context as a library author. Suppose I'm writing a Clown Redemption library. It's possible to Dingle a Clown during redemption, but if the Clown has already dingled that's a problem so... should I raise an exception? Alice thinks obviously I should raise an exception for that, she uses a lot of Clowns, the Clown Redemption library helps her deliver high quality Clown software and it's very fast, she has never dingled a Clown and she never plans to, the use of exceptions suits Alice well because she can completely ignore the problem. Unfortunately Bob's software handles primarily dingling Clowns, for Bob it's unacceptable to eat an exception every single damn time one of the Clowns has already been dingled, he demands an API in which there's just a return value from the dingling function which tells you if this clown was already dingled, so he can handle that appropriately - an exception is not OK because it's expensive. Alice and Bob disagree about how "exceptional" the situation is, and I'm caught in the middle, but I have to choose whether to use exceptions. I can't possibly win here.
- alphanullmeric 3y agoLike I said, this argument doesn’t work because you can use options in c++ but you can’t use exceptions in rust. So when there’s an occasion where you want to avoid the overhead of an option or result in rust - well too bad.
- dureuill 3y agoYes you can. They're called panics