Overhead of newtypes and From implementation?

(The answer is always "plan, measure, decide".)
The question is: I am using a bitmap library that is hardcoded to u32. I have many different types of u32 Ids that all need to be stored in them. I also have other things that are u32 that aren't Ids.

I'll have one Bitmap for Ids for TypeOne and another Bitmap for Ids for TypeTwo. No Bitmap will ever contain Ids for different types.

I could:

  • use u32 and hope I don't get terribly confused as to which is which....that never works well
  • use a plethora of TypeOneId(u32), TypeTwoId(u32) and make a Bitmap wrapper which is generic over the "Into + From".

I vastly prefer the second (readability > safety > ignorantly perceived performance costs), but this will be used frequently in a hot loop (imagine database indexes for example). I know the Rust implementation of newtypes have 0 overhead at runtime but what about the cost for Into and From? Is the compiler smart enough to optimise those away as well?

I realise this is like an ignorant child asking Picasso about whether they should use red or green without any more context, but .. help :slight_smile:

For functions this simple, I would expect them to be inlined and optimized away. If you’re really worried about it, you can mark your implementations #[inline(always)].


That's what I'd expect - if the Into and From implementations are MyNewType(the_u32) and my_new_type.0 respectively then I'd hope it would be the like the spoon in the matrix...

Thanks @2e71828!

Like the spoon in the matrix... I love it! Couldn't resist:

struct Spoon(u32);

impl From<Spoon> for u32 {
    // There is no spoon 
    fn from(other: Spoon) -> u32 {

(If I hadn't already marked the other comment as the answer then this would be it ;-))

1 Like

I actually just landed a PR to the compiler that makes constructing MyNewType(the_u32) zero-overhead even without relying on the optimizer: Avoid `alloca`s in codegen for simple `mir::Aggregate` statements by scottmcm · Pull Request #123886 · rust-lang/rust · GitHub

That's always been reliably optimized away in release mode, but now it's so zero-overhead that LLVM doesn't even have to optimize away constructing them :slight_smile:


That's pretty neat @scottmcm!

1 Like