3 ms·
My argument against GC (and which applies similary to JIT-basd runtimes) is that the problems caused by GC pauses have non-local causes. If a piece of code ran
by emtel 5y ago
My argument against GC (and which applies similary to JIT-basd runtimes) is that the problems caused by GC pauses have non-local causes. If a piece of code ran slowly because of a GC pause, the cause of the pause is in some sense _the entire rest of the system_. You can't fix the problem with a localized change.
Programs in un-managed languages can be slow too, and excessive use of malloc() is a frequent culprit. But the difference is that if I have a piece of code that is slow because it is calling malloc() too much, I can often (or at least some of the time) just remove the malloc() calls from that function. I don't have to boil the ocean and significantly reduce the rate at which my entire program allocates memory.
I think another factor that gets ignored is how much you care about tail latency. I think GC is usually fine for servers and other situations where you are targeting a good P99 or P99.9 latency number. And indeed, this is where JVM, Go, node.js, and other GCed runtimes dominate.
But, there are situations, like games, where a bad P99.9 frame time means dropping a frame every 15 seconds (at 60fps). If you've got one frame skip every 10 seconds because of garbage collection pauses and you want to get to one frame skip every minute, that is _not_ an easy problem to fix.
(Yes, I am aware that many commercial game engines have garbage collectors).
- bcrosby95 5y agoI don't want to try to bring up an exception that disproves your rule, but what about something like BEAM, where it has per-process (process = lightweight thread) heaps and GC.
- emtel 5y agoI don't know anything about BEAM, but I don't think single-threading of any form really addresses the underlying problem. If you go to allocate something, and the system decides a GC is necessary in order to satisfy your allocation, then the GC has to run before your allocation returns.
- rbranson 5y agoYou can't share objects across threads (called "processes") in BEAM, so it's very different. The GC only ever needs to pause one call stack at a time to do a full GC cycle. Memory shared across processes is generally manually managed, typically more akin to a database than an object heap.
- imtringued 5y ago>If you go to allocate something, and the system decides a GC is necessary in order to satisfy your allocation, then the GC has to run before your allocation returns. Manual memory management on the heap does not solve this problem at all, it is actually worse at it than most traditional GCs. There is no magical system that allocates an object without executing code.
- imtringued 5y agoYou're absolutely correct. If you could divide your program into multiple garbage collector heaps and then choose which garbage collector strategy (or even no garbage collector) to use then even Java could be used for soft real time applications. The problem is "stop the world including my time critical thread". If you only stop the non critical threads and let the critical threads keep running there is no issue with GCs.