Live data from Hacker News

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

forrestthewoods.com

81–90 of 238 posts

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

#81
post #3

This is one advantage of Ada, where parameters are abstractly declared as "in" or "in out" or "out". The compiler can then decide how to best implement it for that specific size and architecture.

How is that semantically different from Rust?

in - regular function arguments

inout - mut function arguments

out - function return

Is there any additional information that a compiler can infer from Ada’s parameter syntax?

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

#82

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…

edit: I misread the previous post. Ignore this.

How are you using the word simpler? Because to me that implies a combination of more obvious and number of lines of code. Something that a benchmark shouldn't be involved in.

For example asking someone to delete 10 lines of code and instead use go's ` net.SplitHostPort` would be an example of "simpler".

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

#83

Earlier quoted context omitted.

As a Rust beginner that likes to learn the hard way I think I have some insights why Rust seems cumbersome and/or hard for programmers trying it. Rust uses syntax that feels familiar but means completely different things than in pretty much any other language. For example '=' doesn't mean assign handle or copy. It by default means move. 'let' doesn't mean create a name for something. It means create physical space fo…

Rc, Cell & RefCell are suppose to be rare. For example I've got 2,000 line Rust program in front of me and I've used Arc 3 times and RWLock 1 time, that's all. You need to structure your program as a Directed Acyclic Graph (DAG), with things interacting only with the things below them in the graph. Then occasionally you might need to break the DAG structure by using Rc, Cell & RefCell, etc...

The thing is not everything can be expressed as a DAG.

And finding it towards the end of writing your program after hours of fighting with borrow checker is extremely unpleasant.

And I don't think I ever landed in the situation where I could fix the discrepancy by sprinkling in few Rc, RefCells and such.

So I prefer to write with RefCells from the start and when I got the thing working and I am ambitious enough then I look at which parts could be borrows instead and I swap them out.

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

#84
post #81
post #3

This is one advantage of Ada, where parameters are abstractly declared as "in" or "in out" or "out". The compiler can then decide how to best implement it for that specific size and architecture.

How is that semantically different from Rust? in - regular function arguments inout - mut function arguments out - function return Is there any additional information that a compiler can infer from Ada’s parameter syntax?

The difference between passing by reference vs. by value is observable when comparing pointers to the original vs. to the argument. This difference may be unobservable in Ada though (not sure), so Ada would have more freedom choosing between the two.

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

#85
post #68

Earlier quoted context omitted.

As a Rust beginner that likes to learn the hard way I think I have some insights why Rust seems cumbersome and/or hard for programmers trying it. Rust uses syntax that feels familiar but means completely different things than in pretty much any other language. For example '=' doesn't mean assign handle or copy. It by default means move. 'let' doesn't mean create a name for something. It means create physical space fo…

But Rc is only useful for creating tree-like data-structures. One non-tree cross-link or back-link and you'll have to redesign your entire code.

Sibling and parent pointers are almost universally a sign that an abstract data structure (and associated algorithm) has been mistaken for concrete. The exception that comes to mind first is Knuth's dancing links, and its obscurity is an indication of the rarity of actually needing these pointers. In any case, it's also a poster child for using indices rather than pointers.

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

#86

Earlier quoted context omitted.

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…

Blog 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…

When 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

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

#89

Earlier quoted context omitted.

Rc, Cell & RefCell are suppose to be rare. For example I've got 2,000 line Rust program in front of me and I've used Arc 3 times and RWLock 1 time, that's all. You need to structure your program as a Directed Acyclic Graph (DAG), with things interacting only with the things below them in the graph. Then occasionally you might need to break the DAG structure by using Rc, Cell & RefCell, etc...

The thing is not everything can be expressed as a DAG. And finding it towards the end of writing your program after hours of fighting with borrow checker is extremely unpleasant. And I don't think I ever landed in the situation where I could fix the discrepancy by sprinkling in few Rc, RefCells and such. So I prefer to write with RefCells from the start and when I got the thing working and I am ambitious enough then…

There are many many many ways you can express something and it's very likely that one of those ways is a DAG.

The issue here is that you are writing C++ code rather than Rust code.

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

#90
post #82

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…

edit: I misread the previous post. Ignore this. How are you using the word simpler? Because to me that implies a combination of more obvious and number of lines of code. Something that a benchmark shouldn't be involved in. For example asking someone to delete 10 lines of code and instead use go's ` net.SplitHostPort` would be an example of "simpler".

I've read that good generals worry about tactics and great generals worry about logistics.

Good programmers play code golf, great programmers write readable and maintainable code.

Your example seems reasonable but programmers also like to act like the smartest one in the room. I often come across tricky and borderline obfuscated code because somebody wanted to look clever. This is a logistical nightmare.

Post reply on HN