Does GC in OCaml only happen when allocating memory?

Expanding slightly (and hopefully correctly!), as I don’t think the paper explicitly covers the implementation detail of the first question. It’s necessary to consider the two parts of the GC (minor and major), as their parallel properties are very different. Each domain pauses what it is doing to do either some sweeping or marking, but other domains continue to be able to do work.

When the minor GC is run, no user code is running - all the domains perform a minor GC in parallel with each other, but user code (the “mutator”) is stopped while this is done.

In order to start a minor GC (and, very briefly, in order to conclude a phase of the major GC) it is necessary to “stop the world” - i.e. to get all domains to pause the mutator (user code!). If a domain is blocked (usually on I/O) then the runtime lock for that domain is released, but the OS thread running the domain is not able to respond to a request for to stop-the-world. That’s obviously dreadful as the whole program grinds to a halt, with all the other domains waiting to be able to run the GC. This is where GC backup threads come in - when the main OS thread running the domain blocks, the backup thread steps up and “watches” for stop-the-world requests - so if a domain is blocked on I/O, the backup thread performs minor GC work for it.

So while it’s true that there are dedicated GC threads in the background, they’re probably not what you meant - i.e. there are not separate OS threads for running mutators and specific ones for parallel execution of the GC.

6 Likes