7 ms·
What's the performance of Go's GC like against the JVM's? Especially since both languages are about the same abstraction level and roughly the same speed (3x sl
by sansnomme 7y ago
What's the performance of Go's GC like against the JVM's? Especially since both languages are about the same abstraction level and roughly the same speed (3x slower than C for general unoptimized code excluding startup time).
- hyperpape 7y agoI don't know of any direct comparisons of JVM and Go GC efficiency. However, the biggest difference is that there's only one Go GC, while there are several supported ones for Hotspot. With the exception of CMS, which is deprecated, those collectors occupy different niches, meaning there are times you'd use each of them.[0] The Go collector is optimized for relative simplicity and low latency, and currently tolerates significant overhead to hit that target. [0] Maybe Shenendoah and ZGC are close enough that they're just direct competitors? Perhaps they're even designed to supercede G1? I'm not quite sure about that, but even so, it would leave at least 2-3 options, depending on whether you include Serial/Epsilon as serious options.
- pron 7y agoGo's collector is similar to OpenJDK's deprecated (about-to-be-removed) CMS (applied to the entire heap, rather than just the old generation, as in OpenJDK). They're both concurrenct non-moving mark and sweep collectors.
- HALtheWise 7y agoIt's fundamentally difficult to compare them, because the features of the language itself change the workload the GC faces in a typical program. For example, Java boxes almost all values, so can't store very much on the stack. That means that conventional Java programs (typically) generate many more short-lived heap allocations than Go programs. For more, see the excellent blog post here: https://blog.golang.org/ismmkeynote https://blog.golang.org/ismmkeynote
- hyperpape 7y agoI haven't put real thought into this, but it seems that in principle, given enough understanding of the runtimes, you can create good benchmarks of the collector. You would have to find patterns that force it to allocate/collect similar amounts of data, but that's doable. However, to your point, so far as the languages tend to allocate more or less data on the heap, that might change which benchmarks look good, the same way that you'll care about different automotive benchmarks if you want to tow a trailer or race.
- hilbertseries 7y agoIt's also a little difficult to benchmark Go GC the way you can the JVM, because you can't set a maximum heap size in Go. So, if you create objects too fast you'll just run out of system memory.
- lykr0n 7y agoI would wager that Java's GC is better just for the simple fact that it has a whole bunch of knobs you can turn based on your workload. I've investigate an issue with a very time Go program, and the performance of it was being harmed by the Garbage Collector.~600ns GC doing 2k GC/s per second- ~12% of its time was spent garbage collecting. The solution was to turn the GOGC to 37- this yielded the best results but only increased performance 5%. My coworkers were saying how they had 100s of knobs they could turn and try to try and tune the GC to either reduce the number of pauses, or do one big one every 10 seconds. . Java's options are more then I wish to list here. Go has `GOGC=` and that's it. As one to one performance, that would be hard to measure, but my guess is Java would win in the end.
- kccqzy 7y agoI would guess the same. Go's GC is narrowly tuned towards server workloads with pretty low latency. That means batched workloads (such as the Go compiler itself!) is hurt by GC. Here's a nice presentation transcript that summarizes the design decisions behind Go's GC: https://blog.golang.org/ismmkeynote https://blog.golang.org/ismmkeynote And as you can see, it's basically entirely driven by low latency, but not necessarily high throughout. Another point to consider besides GC is that Java at least has JIT which really benefits hot paths; Go does not.
- kapilvt 7y ago“At least has a jit”, go is compiling to native code, Java is to a jvm bytecode instruction executed effectively by a interpreter, a jit is critical to good performance in the latter. In the former, ie. go you have control over memory layout and are already in machine code at execution the constructs of the language aka runtime are effectively a linked library instead of a virtual machine. Golang prefer one simple way over playing with runtime knobs. That said the gc characteristics of go, are partly reactionary to java at that time (10yrs ago) unpredictable latency and pauses, and they optimized to address that also in response to early prod users. All gc languages have gc overhead from a throughput perspective 15-20% afaics
- Twirrim 7y ago
- cozos 7y agoThis is an interesting article on the topic: https://blog.plan99.net/modern-garbage-collection-part-2-1c88847abcfd https://blog.plan99.net/modern-garbage-collection-part-2-1c8... https://www.reddit.com/r/golang/comments/5j7phw/modern_garbage_collection/dbe958e/?context=10000 https://www.reddit.com/r/golang/comments/5j7phw/modern_garba... > "Go: 67 ms max, 1062 pauses, 23.6 s total pause, 22 ms mean pause, 91 s total runtime > Java, G1 GC, no tuning: 86 ms max, 65 pauses, 2.7 s total pause, 41 ms mean pause, 20 s total runtime" What I got from this is that Go has faster GC pauses at the cost of throughput (i.e. more pauses resulting in higher total pause time). The new JVM Shenandoah GC also makes this tradeoff by adding another layer of indirection ("Brooks forwarding pointer") which has a throughput performance cost but gives you really low GC pauses.