`&u64` vs. `u64` as input

I have two related questions inspired by a SetU64 that I'm developing for the next generation of tinyset. They regard the API for methods like contains (or remove). The standard sets take [Borrow](https://doc.rust-lang.org/std/collections/struct.HashSet.html#method.contains), since the code needs to work for "big" types like strings that you don't want to clone. For a small Copytype likeu64` it feels like a wasteful complication to take references as input rather than just accepting the value you're looking for.

So my two questions are:

  1. Which API would you prefer as the user of a set crate?

  2. So you know if there could be a performance cost to accepting a reference rather than a value?

For the first question, the advantage of accepting a reference is that it allows to easily switch between container types. The advantage of accepting values is that if you aren't switching containers it's a bit more direct and intuitive (to me, anyhow). And if there is a performance advantage (see question 2), then that would be a reason not to use references.

For the performance question, naively one would expect that passing values would be cheaper than passing references, because they could be held in registers and the came would never have to be placed in slow RAM. However, I could also imagine that the compiler would recognize that it's easier and cheaper to pass a value than a reference and make that optimization. Does anyone know if it does this, or should be relied on to do so?

Clippy has a lint that warns you when a Copy value would be cheaper* to pass by value - this makes me think that you can't rely on the compiler to do it for you. I'm not 100% sure though.

* Cheaper being defined as 'is it smaller than two general purpose registers on a 32 bit system'

1 Like

Any idea why the choice was made to make the reference width 32 bits here? 64 bit seems more natural, but there's likely something I'm missing there.

TWO gp registers on a 32 bit machine is 64 bits if I'm not mistaken...

Yes, and? My question is why they didn't go for the size of 2x64bit GP registers rather than 2x32bit.

Ah OK. Maybe because then it would be a bit expensive on 32 bit?

Probably because ARM32 is still pretty common, and WASM is 32-bit.

Yep, portability is the reason:

This lint is target register size dependent, it is limited to 32-bit to try and reduce portability problems between 32 and 64-bit, but if you are compiling for 8 or 16-bit targets then the limit will be different.

1 Like