4 ms·
IIRC Go has "GC assist" which forces goroutines that allocate too frequently to assist in GC work (share CPU time, i.e. they're slowed down), and I've never see
by kgeist 2y ago
IIRC Go has "GC assist" which forces goroutines that allocate too frequently to assist in GC work (share CPU time, i.e. they're slowed down), and I've never seen anything like that described for Java/C#. Interesting approach.
- gf000 2y agoIn other words, it slows down the user's code randomly. I wouldn't call that a necessarily good tradeoff.
- kgeist 2y agoIt's a back-pressure mechanism. I think slightly slower code on average is better than unexpected long GC pauses.
- gf000 2y agoBut an important code that has to allocate a lot will be disproportionately affected by this. Also, it doesn't solve "unexpectedly long GC pauses" just somewhat lowers their frequency. Java's ZGC is multiple generations ahead, and I believe is a fairer tradeoff (overall lower throughput (due to read barriers over write barriers), but guaranteed <1ms pause time due to basically everything happening concurrently)
- kgeist 2y agoGo's garbage collector is concurrent, too. GC assist makes sure the GC can keep up with allocations.
- gf000 2y agoCorrect me if I'm wrong, but concurrent GC only means that certain phases of GC can be done in parallel. GC pauses are a necessity exactly for the part that can't be done in parallel, and Go is definitely not using ZGC's next-generation design that would decouple the pause's length from the heap size, so we still have our "arbitrary long pause" problem on the table.
- kgeist 2y agoFrom Go's docs: >The Go GC avoids making the length of any global application pauses proportional to the size of the heap, and that the core tracing algorithm is performed while the application is actively executing. >Brief stop-the-world pauses when the GC transitions between the mark and sweep phases. I didn't benchmark it myself, though. Go is mostly used in stateless microservices where huge heap sizes are very uncommon. We usually scale horizontally, not vertically. Also, Go has value objects which can be allocated on the stack or embedded inside other objects, so it allocates far less garbage than Java. So practically for me Go's GC has been a non-issue, I barely remember it even exists.
- yvdriess 2y agoGo GC's stop the world pauses are essentially synchronization barriers at the start and end of a GC phase. That pause length is a function of the number of worker threads, not the size of the heap. You can check this yourself by running the tile38 and cockroachdb benchmarks with GODEBUG=gctrace=1 .
- gf000 2y agoIt's the function of both, as per even the sibling comment. Obviously there is not much to synchronize when there is only a single thread.
- yvdriess 2y agoAny concurrent GC will have an unpredictable impact on application threads. The more obvious is the necessary synchronization on GC startup and shutdown, e.g. to turn on write barriers during GC. Less obvious but perhaps more impactful is the cache trashing incurred by the GC threads' heap traveral.