[1] https://github.com/dotnet/roslyn/issues/118
[2] https://github.com/dotnet/corefxlab/blob/master/docs/specs/s...
"C# heap allocations aren't expensive and are faster than C/C++. They are even faster than stack allocations (if the stack alloc is too large to be a register) as the stack needs to zero out the memory first; whereas the heap has done this ahead of time. However, they do come at a cost, which is deallocation.
C/C++ have both an allocation and deallocation cost. The main advantage is you know when you are paying that deallocation cost; the main disadvantage is you often do it at the wrong time or don't do it at all which leads to memory leaks, using unallocated memory or worse trashing something else's memory (as it has been reallocated).
The GC isn't the bad guy; its the liver and blaming it is like blaming a hangover on the liver.
However; the free drinks the clr allocation bar gives you are very tempting, and does mean there is a tendency to over indulge so the hangovers can be quite bad... (GC pauses)."
[1] https://github.com/dotnet/roslyn/issues/10378#issuecomment-2...
Also, doesn't C# have the ability to limit (or pretty much disable) GC?
Historically, many game engines have a "never allocate" policy: Everything is done with static buffers and arenas of temporary data. The broad strokes of this policy are mostly achievable in a GC language that allows value type collections(fewer managed references = less to trace = cheaper garbage). The problem typically comes in little bits of algorithmic code that need their own allocation: Because the language is garbage collected, all your algorithms are using the GC by default. And if you want to reclaim it, you have to fight a very uphill battle.
IME, though, most of the problem is resolvable if you have enough introspection into GC configuration. If a game can tell the collector that it needs a cheap scratch buffer to process an update loop and then get thrown out, that covers a lot of the problem. The last bit of it is fine detail over memory size and alignment, which some GC languages do give you introspection into already.
Edit: Also, I should note that the relative value of GC changes a lot when your process is long-lived and unbounded in scale(servers) or involves a lot of "compiler-like" behaviors(transformations over a large, complex data graph). The advantage of doing without it in a game engine has a lot to do with the game being able to be tuned around simple processing of previously authored data, with limited bounds in all directions.
Players notice when the framerate drops. Presuming a pretty typical 60 Frames Per Second you have a tight 16.6ms time budget to do all of the work for the entire frame. All of the physics, all of the sound processing, all of the AI and everything else needs to be sliced up into little bits that can be distributed across the time the game is played.
There are many good ways to achieve this, and many ways that just appear good until someone else plays your game. If you allocate dynamically even occasionally you need a strategy to allocated about as much as you deallocate each frame or otherwise mitigate the costs.
C++ has this problem completely solved with strong deterministic semantics between destructors, smart pointers and allocators. This can be handled in C# a few ways as well, but sometimes a bunch of unallocated memory builds up and is cleaned between level loads or during downtime. When the Frame rate drops because the garbage collector consumes 1 of the 2 hardware threads in the middle of a firefight players get mad. If you only ever tested on your nice shiny i7 with 8 hardware threads you might never notice until a bug report lands in your inbox. That presumes it wasn't one of the stop the world collections and you couldn't use that last hardware thread better than the GC, both of which negate GC altogether.
Done right deterministic resource allocation costs almost nothing. You can get to zero runtime cost and nearly zero extra dev time. In practice a little runtime cost is fine, and a little time spent learning is OK, but a bug report in the final hour before shipping that the frame rate drops on some supported hardware setups but not others is really scary.
In practice, most games don't have entirely reliable performance, particularly on low-end hardware.
Drop a frame in a competitive First Person Shooter and be ready for death threats.
Drop a frame in an angry birds clone and be ready for 5 stars in a review just because you made your first game.
I suspect you could could get away with quite a bit of GC in most games. But by the time you learn whether or not you could get away with you have fully committed to language for several months. Unless you fully committed to D you are stuck with your memory management strategy. In order to be risk averse game devs dodge GC languages entirely because the benefit is small compared to the potential gain. Combine this with how everyone wants to make the next super great-<insert genre here> MMO that will blow everyone away, they think that they must squeeze every drop of perf out of the machine and sometimes they are right.
Lua is hugely popular for scripting in games. World of Warcraft used it to script the UI. Its garbage collector can be invoked in steps. You can tell it to get all the garbage or just to get N units of garbage. If you tell it to get 1 unit of garbage each frame while frugally allocating I expect you could easily meet the demands of many casual games.
Then there are games like Kerbal Space Program. All C# and all crazy inconsistent with performance. It will pause for no apparent reason right as you try to extend your lander legs and cause you to wreck your only engine on a faraway planet. I cannot say with certainty it is GC, but that cannot be helping.
Just be a good citizen and don't trash like crazy and the GC will never block in the action phase.
Also, don't use the default mono GC, that one is terrible.