Live data from Hacker News

Should small Rust structs be passed by-copy or by-borrow? (2019)

forrestthewoods.com

151–160 of 238 posts

Re: Should small Rust structs be passed by-copy or by-borrow? (2019)

#151
post #115

Earlier quoted context omitted.

I work in a Rust codebase that uses a lot of functional functions, and I’ll say this: on average the imperative style takes less lines of code and less indentation. I also find it more readable personally, and idiomatic.

Functional iteration is good for the same reason we use for loops over while loops, and while loops over goto: they are more constrained, more clearly communicate intent, and are therefore easier to reason about.

Sure but it’s easy to go overboard with this stuff. Reduce (fold) especially can be pretty hard to read in hairy situations.

My general rule is that if you need fewer lines of code to implement your logic with a simple for loop, you probably should.

Re: Should small Rust structs be passed by-copy or by-borrow? (2019)

#152
post #143

Earlier quoted context omitted.

> There's a reason that ancient software running on ancient hardware is way more responsive & snappy than what we have today. Laziness. Laziness in terms of using entirely inappropriate algorithms, sure. Laziness in not microbenchmarking minutia? It shouldn't be. There's a limit on how much that can hurt you. I would say much less than a factor of ten, but let's go with 10x just for argument's sake. If you have a CPU…

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…

This has been my experience too. I wrote a text crdt last year which improved automerge’s (then) 5 minute runtime. My code currently takes 6ms to do the same work.

Automerge’s design assumed this stuff would always be slow, so they had this whole frontend / backend code split so they could put the expensive operations on worker threads. Good optimizations in the right places make all that complexity unnecessary. The new automerge is shaping up to be simpler as well as faster.

Re: Should small Rust structs be passed by-copy or by-borrow? (2019)

#153

Oh neat, that’s my blog. My old posts don’t resurface on HN that often. Lots of criticism of my methodology in the comments here. That’s fine. That post was more of a self nerd snipe that went way deeper than I expected. I hoped that my post would lead to a more definitive answer from some actual experts in the field. Unfortunately that never happened, afaik. Bummer.

My only criticism is the “ugly mess” part. You can implement the traits on references too.

True, that does work for traits. But it's super annoying if you have to write multiple copies of the same thing. That can get out of control quick if you need to implement every combination.

And that doesn't help at all if you're writing a "free function" like 3D primitive intersection functions. I suppose you could change that simple function into a generic function that takes AsDeref? Bleh.

Re: Should small Rust structs be passed by-copy or by-borrow? (2019)

#154
post #119

Earlier quoted context omitted.

> 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.

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?

Re: Should small Rust structs be passed by-copy or by-borrow? (2019)

#155

I always prefer by-borrow. That's because in the future this struct may become non-copy and that means some unnecessary refactoring. My thinking is a bit like "don't take ownership if not needed" - the "not needed" part is the most important thing. Don't require things that are not needed.

If it's a 3D real-valued vector, or similarly basic structure, you can be fairly certain, that it will stay copyable.

I agree. Being copyable is part of the signature for something like this. Explicitly so in rust.

Re: Should small Rust structs be passed by-copy or by-borrow? (2019)

#156

Earlier quoted context omitted.

How do you express as a DAG a tree where nodes need to keep references to their children and parents? Two separate synced trees? Is it worth it? > The issue here is that you are writing C++ code rather than Rust code. How dare you! I'm writing TypeScript code! ;-) Rust is not Forth. I can write whatever I want and there's nothing wrong with that.

> How do you express as a DAG a tree where nodes need to keep references to their children and parents? Rewrite your program in a form where it does not contain a tree. If you want an actual tree as a data structure, see the trees crate. > Rust is not Forth. I can write whatever I want and there's nothing wrong with that. And other people write Haskell code in Python :p. If your code style doesn't match the language…

I think Rust is flexible enough to still work very well with my style.

But you inspired me about something. I think I can rewrite the program that I am writing to use reverse Polish notation instead of a tree. Thanks!

Re: Should small Rust structs be passed by-copy or by-borrow? (2019)

#157

I don’t feel like this gave a satisfactory answer the question. Since everything was inlined, the argument passing convention made no difference in the micro benchmarks. But what happens when it does not inline? Then you would actually be testing by-borrow be by-copy instead of how good rust is at optimizing.

I feel like they got excited by their C++ code being so much slower and curious about the "weird" C++ result and forgot to figure out the original question.

>"C++ code being so much slower"

  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  Delta: -0.0227428%

So it appears that C++ - Windows LLVM 15 beats Rust by large margin.

Re: Should small Rust structs be passed by-copy or by-borrow? (2019)

#158

Earlier quoted context omitted.

This x 10000 ! If I had a dime for every time I provided this exact feedback in code reviews…I find surprising that a lot of devs in tech industry are obsessed with pointless micro optimizations and they don’t care about writing maintainable, testable simple code. My final comment is always to not outsmart compilers/jvm because they tend to do a much better job that developers. Please, don’t optimize unless you have…

It depends on your specialization, I guess. If you're making a website, a few microseconds here and there probably don't matter. But in my field (Fintech), performance really does matter. Doing the simple, slow thing is just lazy and won't make it through review.

Great. Should be easy to prove then.

Re: Should small Rust structs be passed by-copy or by-borrow? (2019)

#159

A 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).

I would still consider myself a go novice, but I have been burned a number of times passing simple objects by reference and then that object gets mutated causing subtle bugs. Also, go is happy to blow your foot off if you take the reference of a loop variable. Although, there is a proposal to fix that.

Generally I find that less bugs get introduced when using copy instead of pass by reference, but I’m sure others have the opposite opinion.

Re: Should small Rust structs be passed by-copy or by-borrow? (2019)

#160

Earlier quoted context omitted.

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).

I would still consider myself a go novice, but I have been burned a number of times passing simple objects by reference and then that object gets mutated causing subtle bugs. Also, go is happy to blow your foot off if you take the reference of a loop variable. Although, there is a proposal to fix that. Generally I find that less bugs get introduced when using copy instead of pass by reference, but I’m sure others hav…

[deleted]
Post reply on HN