5 ms·
I sort of agree and sort of disagree. > Then you would actually be testing by-borrow be by-copy instead of how good rust is at optimizing. I don’t think the q
by ncallaway 4y ago
I sort of agree and sort of disagree.
> Then you would actually be testing by-borrow be by-copy instead of how good rust is at optimizing.
I don’t think the question is actually: “what is faster in practice, a by-copy method call or a by-value method call”, I think the question is: “as an implementer, which semantics should I choose when I’m writing my function”.
For the second question: “Rust is usually pretty good at aggressively inlining, so… if you’re willing to trust Rust’s compiler, you’re often okay going with by-copy implementations, but you should keep an eye on it”. Whereas, as you note, for the first question it’s not an answer.
But, I do think if someone was going to put more work into it I’d be very curious what the answer to the first question is. If I’m choosing to implement with by-copy semantics and trusting the Rust compiler to hopefully inline things for me, I’d like to know the implications in the cases when it doesn’t.
- forrestthewoods 4y agoBlog author here. This feels like the best summary in this comment section. The root question is indeed “what semantics should I use”. And the answer I came up with was “the compiler does a lot of magic so by-copy seems pretty good”. I agree with the previous commenter this is not a satisfying conclusion! My experience with Rust is that it requires a moderate amount of trust in the compiler. Iterator code is another example where the compiler should produce near optimal code. Emphasis on should!
- FpUser 4y agoWhen value size is small (whatever "small" means for particular architecture) I'd say "trust the compiler" suggestion is reasonable. When the size grows there should be no more "trust" unless compiler can decipher if it is safe to use ref instead of value basing on value size (we assume that the function does not mutate the value). Your tests on my PC: Rust - By-Copy: 14124, By-Borrow: 8150 C++ - By-Copy: 12160, By-Ref: 11423 P.S. Just built it using LLVM under CLion IDE and the results are: G:\temp\cpp\rust-cpp-bench\cpp\cmake\cmake-build- release\fts_cmake_cpp_bench.exe Totals: Overlaps: 220384338 By-Copy: 4397 By-Ref: 4396 Delta: -0.0227428% Process finished with exit code 0
- nicoburns 4y ago> When the size grows there should be no more "trust" unless compiler can decipher if it is safe to use ref instead of value basing on value size I believe that the Rust compiler at least does exactly that. Large structs will be passed by reference under the hood even if it passed by value in the code. I suspect C++ compilers do the same, although I'm not sure about that.
- FpUser 4y agoNow comes big surprise: I just built it using LLVM under CLion IDE and the results are: G:\temp\cpp\rust-cpp-bench\cpp\cmake\cmake-build- release\fts_cmake_cpp_bench.exe Totals: Overlaps: 220384338 By-Copy: 4397 By-Ref: 4396 Delta: -0.0227428% Process finished with exit code 0
- josephg 4y agoWhy is performance so much better in this case? That seems like a suspiciously large delta from the first test. Were the other benchmarks run in debug mode / with optimizations turned off or something like that? What compiler & flags are you using?
- FpUser 4y ago>"Were the other benchmarks run in debug mode / with optimizations turned off or something like that?" Why would I do something like that? Of course all builds are release mode, optimize for speed. Rust - Windows - By-Copy: 14124, By-Borrow: 8150 C++ - Windows MS Compiler - By-Copy: 12160, By-Ref: 11423 C++ - Windows LLVM 15 - By-Copy: 4397, By-Ref: 4396 >"Why is performance so much better in this case?" Not sure and not in a mood to investigate. I do know if cache locality and branch prediction stars line up properly the performance difference can be staggering. Maybe LLVM has accomplished something nice in this department.
- forrestthewoods 4y ago