3 ms·
I know this is only responding to your one example, and perhaps your statement is still true generally, but I think that in this particular case it is not. In
by RomeoDelta 6y ago
I know this is only responding to your one example, and perhaps your statement is still true generally, but I think that in this particular case it is not.
In this godbolt [0] I tried using the safe version of equals with two values (from stdin so it can't just optimize the computation away, though I don't think it would) and it seems that when the compiler inlines the equals function, the inefficiencies are removed (which can be seen in the example::main section of the output; lines 212-216 look nearly identical, if not identical, to equals_unsafe in your example).
Please let me know if I'm missing something or if there are any other safe APIs to be wary of.
[0] https://rust.godbolt.org/z/W8dqaK https://rust.godbolt.org/z/W8dqaK
- ridiculous_fish 6y agoRight, the branch may or may not be optimized out; probably it depends on llvm's alias analysis. That's not good, it means you might break it accidentally. IME Rust is more dependent than C++ on these fragile optimizations. I think it is because idiomatic Rust is more abstract, and also because C++ has more advanced specialization features which allows implementing optimizations directly. For example in C++ you can say "if the type is uint8_t then do this instead..." but this is harder in Rust. You asked for other examples: consider a simple operation over an array, like bitwise not. A C-style for-loop does the obvious thing but idiomatic Rust emits a gazillion one-byte 'not' instructions. This doesn't involve 'unsafe' but it does illustrate that you really do have to babysit Rust to get efficient codegen. https://rust.godbolt.org/z/PjW5vo https://rust.godbolt.org/z/PjW5vo (In fairness C++ has its own stupid pitfalls too: https://travisdowns.github.io/blog/2019/11/19/toupper.html https://travisdowns.github.io/blog/2019/11/19/toupper.html)
- RomeoDelta 6y ago> the branch may or may not be optimized out That's true, and while I agree that it is a concern, is there ever a way to gain both ergonomics and optimization? In other words, aren't we always leaving it up to the compiler one way or another? You mention C++'s specialization, and I suppose that is a solution, but then you are (potentially, I can't say for certain) sacrificing compile times. Although I will admit that this is probably a fair trade for certainty of optimization, and it would be nice if Rust at least offered some amount of specializing. > you really do have to babysit Rust to get efficient codegen. https://rust.godbolt.org/z/PjW5vo https://rust.godbolt.org/z/PjW5vo Oh wow, that is interesting. Yeah, that probably speaks to Rust still being a relatively new language, although I would have expected LLVM to do something about that... In any case, that's certainly no zero-cost abstraction. Thanks for the neat info!
- archi42 6y ago> you really do have to babysit Rust to get efficient codegen Reminds me of the time we had to write a high performance SQL engine at university. In Java, and it boiled down to exactly the same realization: We spent a lot of time babysitting the GC instead of actually making the actual SQL engine better. The plan was to use C++ instead, but that option was dropped by the lecturer shortly before the project started :/