3 ms·
Something of a false dichotomy - perhaps. The fact is that allocating at all during realtime operation is frowned upon. Given that the best approach is pre-allo
by Recurecur 6y ago
Something of a false dichotomy - perhaps. The fact is that allocating at all during realtime operation is frowned upon. Given that the best approach is pre-allocation and then turning off the GC, why carry the overhead of the GC at all?
For 99% of realtime work, the Rust or Scala Native approach is just fine. No GC required. Julia users can just use the pre-allocation approach.
The important thing is avoiding language patterns that encourage needless allocation.
- WorldMaker 6y ago> Given that the best approach is pre-allocation GC languages still support stack allocation, you don't have to pre-allocate anything you can stack allocate. (That's where .NET Core has been especially burning rubber in recent releases. Span<T> is a stack allocated, GC-safe "pointer", for instance, that is doing all sorts of heavy lifting in .NET Core performance-critical work these days. It's still early too, as not everything has moved to Span<T> that can move to Span<T> and family.) But also, not everything needs to be pre-allocated for the "best approach". There's some work to get used to the feel of any specific GC, but most modern "VM" GCs (.NET and today's Java, not yesterday's) are multi-generational and there's a lot you can do in strategies such as "focus on the nursery and the LOH" (using only [potentially many] small short-lived objects and a few, mostly stable "very large" objects, avoiding the intermediate generations). > why carry the overhead of the GC at all? Safety. (Why wear seatbelts?) Rust's borrow checker is great but it still requires a lot of manual adjustment and it's still possible to miss something (it's not easy, certainly, but it is possible); a GC gives you safety by default, with no manual intervention required to guarantee safety, and requires manual effort to write unsafe code. > The important thing is avoiding language patterns that encourage needless allocation. That's where we agree and why I'm very adamant that though some of the tools ("knobs") look scarily different in performance optimization for GC versus non-GC languages, the vast majority of the tools are the same: know the O(memory) of your algorithms, and make smart trade-offs regarding that O(memory), avoid allocating what you don't need, know your trade-offs between pre-allocation and allocation only when necessary, etc.
- danielscrubs 6y ago> it's still possible to miss something Could you elaborate?
- WorldMaker 6y agoTbf, I've not directly worked in Rust so my understanding is mostly academic of a sort. The issues I'm directly aware of are primarily in boundary conditions between unsafe and borrow-checked code, which isn't entirely fair to Rust as GC-languages of course have the same boundary conditions. My impression however is that because the borrow checker is a lot of work, there's a lot more Rust libraries in the wild with unsafe code sections than strictly need to be (as compared to similar libraries in GC-languages, and especially with modern tools like Span<T> in .NET nearly shrinking GC-unsafe blocks to non-existent in modern code).