Incremental garbage collection

Gregor Mückl gregormueckl at gmx.de
Sat Jan 29 17:32:32 UTC 2022


On Thursday, 20 January 2022 at 23:56:42 UTC, Chris Katko wrote:
> I just found out that Unity has incremental garbage collection. 
> I didn't know that was a possibility for GCs.
>
> https://docs.unity3d.com/Manual/performance-incremental-garbage-collection.html
>
> I'm just curious what the D language community's thoughts are 
> on it. The tradeoff is: For
> a longer total time / lower throughput, you reduce stress on 
> individual frames which prevents hiccups. That's pretty darn 
> important for games and soft/hard real-time systems.
>
> Is that an option on a hypothetical level, for D? Or does D's 
> language design preclude that. I recall some sort of issue with 
> using Java/C#/whatever's garbage collector because it would 
> have to insert memory barriers into D to work or something like 
> that.
>
> Also, it's hard to find one specific place for "news" regarding 
> D's garbage collector development and "omg we deleted 
> everything GC from the standard library" projects. Are there 
> any major updates on those fronts?

Just to add to this for completeness sake: a while ago I spent a 
few hours digging through Uneal Engine source code to understand 
their GC algorithm. It's a peculiar and interesting take on 
iterative, precise, conservative garbage collection:

- First of all, UE4 has precise runtime reflection information 
for all data types that are handled via the GC (everything 
derived from UObject - which is mostly game logic code). Heap 
scans are optimized aggressively based on this data. Pointers are 
regular naked C++ pointers without any additional magic. They 
need to be annotated for the custom preprocessor that generates 
the reflection data, but that's it. The C++ code touching these 
pointers is plain old code using naked pointers. No hidden 
wrappers there.

- The algorithm is basically mark and sweep with a couple of 
awful situational hacks that stem from weird engine subsystem 
interactions. I'll gloss over those. The GC performs a multistep 
GC process. Each frame, the engine prompts the GC to run one step 
in a stop-the-world fashion.

- Each step, the GC can either run an *entire* mark phase or a 
single step of the sweep phase. The mark step is always run in 
its entirety, never in multiple steps. The sweep phase is broken 
up into steps that free a limited number of marked objects in 
each step. The rest is deferred to the next step. When sweep 
phase is done, the next GC step will be a new mark phase.

IMO, this is a very pragmatic approach. But for the runtime to be 
truly bounded, the heap size needs to be bounded, too. I assume 
that this works for UE4 because for most games using the engine, 
the number of objects involved in the game logic at any point is 
fairly small (mostly ~ a few hundred). Stopping the world for the 
mark phase is also a major simplification. This avoids the 
overhead typically incurred by GC algorithms that do incremental 
marking. Also, GC references can be treated just like regular 
pointers.

I don't know how the D garbage collector runtime is split between 
mark and sweep phases. If the sweep phase is indeed the slower 
phase, an option to have that run iteratively might be enticing. 
I would naively assume that this would be lower hanging fruit 
compared to a generational and/or concurrent GC. But then again, 
I don't have a need for any of that at the moment.



More information about the Digitalmars-d mailing list