Should small Rust structs be passed by-copy or by-borrow? (2019)
171–180 of 238 posts
Re: Should small Rust structs be passed by-copy or by-borrow? (2019)
#172A potential lesson here (i.e. I am applying confirmation bias to retroactively view this article as justification for a strongly held opinion, lol): Unless you are gonna benchmark something, for details like this you should pretty much always just trust the damn compiler and write the code in the most maintainable way. This comes up in code review a LOT at my work: - "you can write this simpler with XYZ" - "but that…
I generally agree, but it’s also not obvious to me in Rust (or in Go) whether passing by reference or by copy is more maintainable or clear. I guess what I want is some guidance on what I should do by default, which you sort of give with “do what is more maintainable”, but I can’t tell what that means in practice (I’ve been told to default to pass-by-reference in the past because most traits take &self and not self).
Re: Should small Rust structs be passed by-copy or by-borrow? (2019)
#173A potential lesson here (i.e. I am applying confirmation bias to retroactively view this article as justification for a strongly held opinion, lol): Unless you are gonna benchmark something, for details like this you should pretty much always just trust the damn compiler and write the code in the most maintainable way. This comes up in code review a LOT at my work: - "you can write this simpler with XYZ" - "but that…
I generally agree, but it’s also not obvious to me in Rust (or in Go) whether passing by reference or by copy is more maintainable or clear. I guess what I want is some guidance on what I should do by default, which you sort of give with “do what is more maintainable”, but I can’t tell what that means in practice (I’ve been told to default to pass-by-reference in the past because most traits take &self and not self).
Re: Should small Rust structs be passed by-copy or by-borrow? (2019)
#174Earlier quoted context omitted.
When I rewrite python code in C, I often hit 1000x speedups, and sub-100x is rare. And that's line-for-line. When I fix an accidentally-quadratic issue, for example, I've seen speedups in the billions without even changing the language. People have lionized Knuth's quote about premature optimization, and used that to ignore performance issues across the board. Since the early '00s, we have not seen a 500x improvement…
> When I rewrite python code in C, I often hit 1000x speedups, and sub-100x is rare. And that's line-for-line. When I fix an accidentally-quadratic issue, for example, I've seen speedups in the billions without even changing the language. And neither of those is a microbenchmark thing, which is kind of my point. I'm surprised language would hurt that much, but that's enough to break things on its own without any laye…
The point I'm making here is that every line matters -- not just the hotspots. If you're suprised that language can have that much impact, perhaps it's time to learn a bit about performance issues that you're being dismissive of?
> I don't think people are talking about 2004 when they talk about the responsiveness of ancient software on ancient hardware.
No, I was responding to your mention of a 500x improvement in hardware. That pipedream ended in the early 00s, and people still talk like Moore's law will absolve their inattentive coding practice. And that felt fine in the decades we went from kHz to GHz, but it's unacceptable today.
Re: Should small Rust structs be passed by-copy or by-borrow? (2019)
#175A potential lesson here (i.e. I am applying confirmation bias to retroactively view this article as justification for a strongly held opinion, lol): Unless you are gonna benchmark something, for details like this you should pretty much always just trust the damn compiler and write the code in the most maintainable way. This comes up in code review a LOT at my work: - "you can write this simpler with XYZ" - "but that…
This seems to be an unpopular opinion, but I feel similarly about how sometimes people seem to toss out `inline` (and even more suspect, `inline(always)` annotations on Rust functions like candy on Halloween and there are almost never any sort of actual measurements of whether it actually helps in the cases it's used. It's not even that I think it really hurts that much in most of the stuff I've worked on (which tend…
Re: Should small Rust structs be passed by-copy or by-borrow? (2019)
#176A potential lesson here (i.e. I am applying confirmation bias to retroactively view this article as justification for a strongly held opinion, lol): Unless you are gonna benchmark something, for details like this you should pretty much always just trust the damn compiler and write the code in the most maintainable way. This comes up in code review a LOT at my work: - "you can write this simpler with XYZ" - "but that…
Blog author here. I somewhat agree, somewhat disagree. This line makes me uneasy: > I always ask them to either prove it or write the simple thing. If the code in question isn't hot enough to bother benchmarking it, the performance benefits probably aren't worth it _even if they exist_. One of my philosophies is that death by a thousand cuts is fine, but death by ten thousand cuts isn’t. A team of 10 engineers can pr…
And actually I still disagree - e.g. I once took over a DMA management firmware and the TL told me "we are really trying to avoid DBATC so we take care to write every line efficiently". But the thing was that once you have a holistic understanding of the systems performance you tend to find _only a small fraction of the code ever affects the metrics you care about_!
E.g. in that case the CPU was so rarely the bottleneck that it really didn't matter, we could have rewritten half the code in Python (if we'd had the memory) without hurting latency or throughput.
Admittedly I can see how games or like JS engines might be a kinda special case here, where the OVERALL compute bandwidth begins to become a concern (almost like an HPC system) and maybe then every line really does count.
Re: Should small Rust structs be passed by-copy or by-borrow? (2019)
#177Earlier quoted context omitted.
Blog author here. I somewhat agree, somewhat disagree. This line makes me uneasy: > I always ask them to either prove it or write the simple thing. If the code in question isn't hot enough to bother benchmarking it, the performance benefits probably aren't worth it _even if they exist_. One of my philosophies is that death by a thousand cuts is fine, but death by ten thousand cuts isn’t. A team of 10 engineers can pr…
> But if you have ten thousand cuts you’re probably doomed. And those don’t show up cleanly in a flame graph. I am reminded of the lovely nanosecond/microsecond talk by Grace Hopper. If your code does a little bit of setup and then spends all of its time in a single hotspot, fine. But if your code is full of microsecond-suboptimal speed bumps, you can probably hide your hotspot altogether. And a flat-ish flame graph…
If your program is still slow, that would also indicate that everything is a problem, ie. the ten thousand cuts. Start optimizing at some obvious spots and then see what happens.
Re: Should small Rust structs be passed by-copy or by-borrow? (2019)
#178Earlier quoted context omitted.
> When I rewrite python code in C, I often hit 1000x speedups, and sub-100x is rare. And that's line-for-line. When I fix an accidentally-quadratic issue, for example, I've seen speedups in the billions without even changing the language. And neither of those is a microbenchmark thing, which is kind of my point. I'm surprised language would hurt that much, but that's enough to break things on its own without any laye…
> And neither of those is a microbenchmark thing, which is kind of my point. I'm surprised language would hurt that much... The point I'm making here is that every line matters -- not just the hotspots. If you're suprised that language can have that much impact, perhaps it's time to learn a bit about performance issues that you're being dismissive of? > I don't think people are talking about 2004 when they talk about…
That depends on how it would have performed if you only transformed the hottest 10% into C.
But I was mainly responding to the idea that micro-optimizations are needed to keep general software snappy, and I don't think they are. If one language is that much faster, that's not micro-optimization.
> No, I was responding to your mention of a 500x improvement in hardware.
What do you mean "No"? I was talking about current hardware being 500x faster than 1988 hardware, which it is. If that's not what you meant by "ancient software on ancient hardware", fine, but that's what my 500x was talking about.
> people still talk like Moore's law will absolve their inattentive coding practice
I'm not trying to excuse inattentive coding. I'm trying to say certain kinds of attention are important and others aren't.
Re: Should small Rust structs be passed by-copy or by-borrow? (2019)
#179Earlier quoted context omitted.
Great. Should be easy to prove then.
Yup, we have a good benchmarking suite to make sure changes don't cause regressions and that optimization changes actually work. That said, I think asking a developer to write everything they do twice so that they can A/B test is overboard. You can come back and really aggressively optimize later, but I think the "default" should be the fast thing, rather than the slow & easy thing.
Re: Should small Rust structs be passed by-copy or by-borrow? (2019)
#180Earlier quoted context omitted.
Now 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
Why 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?
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.