Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

"Remember that whatever works best for you, it’s still better than having to malloc and free by hand. Happy allocating!"

Nice, they are saying exactly the same as those pesky game developers.

https://www.youtube.com/watch?v=tK50z_gUpZI



Yeah, like Tim Sweeney.

"It's interesting that many games can afford a constant 10x interpretation overhead for scripts, but not a spikey 1% for garbage collection."

https://twitter.com/timsweeneyepic/status/880607734588211200

https://wiki.unrealengine.com/Garbage_Collection_Overview

Which was it again, the engine chosen by Nintendo, Microsoft and Google as first party to their 3D APIs?

https://developer.nintendo.com/tools

https://docs.microsoft.com/en-us/windows/mixed-reality/unity...

https://stadia.dev/blog/unity-production-ready-support-for-s...

https://developer.android.com/games/develop/build-in-unity

The anti-GC crowd on the games industry, is no different than the ones that fought adoption of C/Modula-2/Pascal over Assembly, and then fought adoption of C++ and Objective-C over C.

Eventually they will suck it up when the major platform owners tell them it is time to move on.


>"It's interesting that many games can afford a constant 10x interpretation overhead for scripts, but not a spikey 1% for garbage collection."

Why is that surprising?

Games are basically about humans predicting things and random spikes prevent that from happening in time sensitive games. Beyond game play implications, I suspect there's also something about jerkiness in movement that bugs human senses.


It's not entirely surprising, but one might imagine a different approach: always allocate a 1% buffer for an unexpected GC.

It's not a very satisfactory answer (and there are likely much better tradeoffs to be made), but given the 10x and 1% comparison (not entirely apples to apples though) the comment sounds a bit more interesting.


The problem is that with most GC algorithms 1% of the frames take 2x (or even 20x) as long, not that individual frame times vary by 1%.


How do you allocate a 1% buffer of time? The GC issue in games (or any other timing sensitive application) is about the "world freezing", not memory. Which is why incremental GC is a thing. At best, you're borrowing time.


The problem with GC isn't the "spikey 1%", it's the fact that GC implies the "everything is a pointer to an object" programming model, which in turn fragments your memory and destroys your cache.

Performance-oriented code implies everything is on the stack and/or packed into large arrays, at which point you don't need a GC after all.


I guess this mentality leads to the current state of play where all UI related latencies are out of the roof compare to the 80s. At work, I deal with systems that require 16G of heap as the minimum. Funnily when things get rewritten in Rust providing the exact same functionality and the same or better performance the memory requirement goes down 10x (or more). It is up to us how much garbage our systems producing, how much CO2 is wasted on this. I guess many of us are ok with it. While some of us are not. https://blog.discordapp.com/why-discord-is-switching-from-go...


I've seen multiple production systems rewritten in Rust and the consensus of the developers working on it is that, while the Rust version was more performant, the majority of that performance is attributable to the rewrite itself and not the language. And that a performance-focused rewrite in the original language would have also seen huge performance gains.

As the truism goes, if you require your software to be performant, you must first make Performance a Requirement.


Sure I bet they feel this way. However, if you look at rewrites like the one at Discord[1], it is dead obvious that the rewrite helped not because of the rewrite by itself but because there is no GC (mostly) and some other smaller things (better data structures for certain tasks). In my experience working a lot for the fortune 500 in the last 15 years is that developers are usually not aware of the low level details of their stack including (but not limited to): networking, garbage collection, concurrency, parallelism. It is the exception (mostly in FAANG companies) when these low level details a very well understood and dealt with. It is no surprise that these companies are picking up Rust because those developers actually understand how much less mental overhead is to work in Rust (once it compiles successfully :) ). I know it is a new language and there are hoops (async/await) but at least we can be sure that there is no need for GC tuning, memory corruption is non existent and a few nice additional properties.

In my mind performance is alway a requirement (and a feature). We just stopped caring a long time ago, because it is easier to think about performance as a hardware or capacity problem, memory as GC problem and so on.

1. https://blog.discordapp.com/why-discord-is-switching-from-go...


When you're doing gamedev & are bumping up against your FPS, the GC is just another form of memory management. Doing GC-per-frame tends to work pretty well with a generational GC (generational hypothesis & frame-by-frame updates go hand-in-hand), but you usually have to take care about long-lived data. That's when you end up getting into more manual memory management combined with a GC. In a way, your GC'd high-level language RTS ends up being your scripting language.

That's how I've been thinking about it with Haskell at least (lots of GC knobs, manual performGC hook, compact regions for having long-lived data, good FFI, as high-level as any scripting language you could hope for)


What's their opinion on Rust?


I would imagine excited. Rust's affine type system is an application of logic theory. OCaml is initially French academic production and (from an anecdotal experience) those academics tend to dis how impure most software (and memory management) is. While Rust does not have the purest theoretical foundations, it's still fresh air and will likely result in people paying more attention to the work of researchers in theoretics.


Before self-hosting, the rust compiler was originally in OCaml so presumably there's an overlap in communities there.


I mean, game developers, not OCaml devs

The point was, they said "do manaual memory management" if you want speed.


Great question. I am really hoping that the non-GC world is taking off with Rust.


How does Rust deal with long-lived objects that cannot be block-scoped (or request-scoped, in the context of a server for example)? A typical example here would be a UI framework, where memory has to be managed for the window and its widgets, and then the entire application is suspended until the next event. The user can open and close windows in random orders, and so on. Perhaps some windows generate a lot of associated data which should be disposed of when that window closes, but can also be dragged over into the other windows and duplicated around, so the data is not “owned” by a single window.

It seems to me that this is where the GC “set and forget” model really shines, since otherwise you just have to do all that work manually using an allocation and a free, or a constructor and a destructor, or some similar pattern. Perhaps Rust has some clever answer for this?


> How does Rust deal with long-lived objects that cannot be block-scoped (or request-scoped, in the context of a server for example)?

The issue is not really the scope, the issue is how many owners the data needs to have. A variable that needs to live longer than a scope, but only has a single owner, can be directly returned from that scope. Once you have the need for multiple owners, the most straightforward answer is "reference count them," but it depends on your exact requirements.

> A typical example here would be a UI framework, where memory has to be managed for the window and its widgets, and then the entire application is suspended until the next event.

GTK heavily uses reference counting. People are also investigating what a "rust-native" UI toolkit would look like; taking strong influences from ECSes. It's an open question if those architectures end up better than refcounts.


It seems like you want a reference-counted pointer: you get shared ownership, and the object is deleted when the last reference to the pointer is deleted.

Similar to C++'s std::shared_ptr


Right, but then you take on a bunch of baggage you don’t have in a GC setting. For instance if you want to make zillions of these objects and delete them you are paying overhead for lots of allocations and deallocations made heavier by the reference counting. You pay time overhead for atomic increment/decrement, and if there are cyclic structures then you pay a big price in the code complexity to deal with them properly and not cause memory leaks.




Consider applying for YC's Summer 2026 batch! Applications are open till May 4

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: