Hacker News new | ask | show | jobs
by masklinn 1889 days ago
> The clone()s and the Vec::new()s are all explicit, making them feel heavier than those other languages, when in reality they're still quite a bit lighter.

That's… not exactly true. `Vec::new` is completely free so that's a different debate, but much as in C++ or C allocations in Rust are much more expensive than in managed languages:

1. system allocators genuinely suck, all of them, though some more than others (iirc macos' is especially bad)

2. managed languages can much more easily specialised allocation strategies (freelists, bump allocators, type-custom allocation strategies), this is either difficult / impossible (no custom allocators) or way more painful (manually pass custom allocators in) in Rust

As a result, allocations in Rust are really tremendously slow by default, it's not too rare to see questions about Rust programs which are slower than managed equivalents, in release mode. Because the rust program is allocation heavy (relatively), it might have 10% the allocations of the non-rust program but the allocations are 100 times more expensive.

1 comments

Interesting, I hadn't heard this before. Do you have any resources I could read?

Edit: I do know that languages where strings are immutable use that fact to do lots of optimization (automatically sharing "copied" strings and just cloning reference-counters, for example), but you can accomplish some of this in Rust too with Rc<> or even persistent data structures if you really want to. And of course there are cases where it's more efficient to actually mutate a string, which these languages can't do. But it sounds like you're talking about something else?

There are three strategies that other languages use automatically that you can also apply in Rust by hand: string interning, small string optimization and "Copy-on-write". For the first and second, you can use some existing crate like https://docs.rs/string-interner/0.12.2/string_interner/ and https://github.com/rust-analyzer/smol_str. For the later, you can use Cow<'_, str> https://doc.rust-lang.org/std/borrow/enum.Cow.html. I'm having trouble thinking of a case where Rc<String> would be appropriate.