Remix.run Logo
tialaramex an hour ago

Casey spends a lot of effort on what he considers an anti-pattern where you're making a huge number of separate objects. I think a lot of this comes from Java, a language where all the user defined types actually are obliged to be heap allocations. If I make a Goose type, and I say I want a Goose, Java will allocate space on the heap for the Goose and put my Goose there, that's really how Java works. If I make a growable array of them ArrayList<Goose>, and add each of 500 geese, that's 500 allocations for geese plus maybe 8 allocations for the ArrayList, so 508 total. Ouch. If making a Goose was itself cheap this overhead hurts badly.

But a lot of languages aren't like that, and so this doesn't translate. Obviously in Rust with Vec<Goose> that's only 8 allocations, each local Goose lives in the stack - or, if you knew up front there were 500 geese, you Vec::with_capacity(500) and it's a single allocation - but similar is true in many languages, Java is an outlier.

ahtihn 43 minutes ago | parent [-]

Maybe I'm missing something but when would the 500 geese instances ever be stack allocated in Rust? That comparison seems unfair, the lifetime of that kind of object isn't going to be compatible with stack allocation.

Allocations are really really cheap in Java by the way, so I don't get how 500 allocations would even be an issue.

tialaramex 25 minutes ago | parent [-]

When you make a local variable with a Goose in Java, that's a heap allocation

    Goose jim = make_a_goose_somehow();  // Java, so jim is on the Heap, no way around it
When you make that variable in Rust...

    let jim : Goose = make_a_goose_somehow();  // Rust, jim is on the stack
Now, if we make a bunch of geese, maybe in a loop, and we put them into our growable array type...

    ArrayList<Goose> geese = new ArrayList<Goose>();
    // ... some loop eventually
      Goose a_goose = somehow_get_this_goose();   // That's an allocation
      geese.add(a_goose);

But in Rust...

    let geese: Vec<Goose> = Vec::new();
    // ... some loop eventually
      let a_goose : Goose = somehow_get_this_goose(); // But this is not
      geese.push(a_goose);