| ▲ | pron 2 days ago | |||||||
If anything, I think it's not unlikely that ZGC will become the default at some point, as it matures. It's hard to beat Parallel on batch workloads, although G1 is getting there. ZGC is unparalleled for low-latency (GC pauses are just gone). G1 is intended to offer a compromise that could be a reasonable default. | ||||||||
| ▲ | cogman10 2 days ago | parent | next [-] | |||||||
I have no qualms with ZGC being the default. The low latency that it offers at near G1 speeds is a very good trade off (IMO). I just have a problem with G1 because in my experience, the best place for it is fairly large heaps. Get something sub 2 or even 10G, especially if you have a few cores to offer, and the parallel and often even the serial collector will give G1 latency even on major collections with superior throughput and overhead. | ||||||||
| ▲ | nickyvdicarlo 2 days ago | parent | prev [-] | |||||||
I would be very surprised if ZGC became the default, because it incurs a significant overhead penalty to eliminate those GC pauses. All else equal you're effectively just sacrificing throughput for latency, since it's doing a bunch of extra housekeeping in the background (foreshadowing...) That's a perfectly reasonable tradeoff to make if low latency is a priority (or perhaps more importantly if having very consisent/predictable latency is a priority) but in most Java projects I've been exposed to that's been a tertiary concern at best. Frankly, I question if most Java developers are even aware that they're allocating physical memory when they type 'new'... In the modern enterprise Java world (that I've been exposed to) it's very common to have a mandate that all components deploy a minimum of N instances across X regions for resiliency. By design that almost always means you're deploying at least 2x more compute than you strictly need, so the top priority is generally minimizing per-instance overhead to minimize cloud spend. For example, the default templates at my current company deploy something like 0.25-0.5 vCPU per instance, and therin lies the rub. ZGC performance is _catastrophically_ bad with <=1 cpus because when there's only one core, any "concurrent" GC events become full on stop the world events. We had someone pilot a change to the default JVM args for all components because they heard that ZGC would reduce latency, only to discover that basically all of our microservices immediately failed their perf tests. For the first one I spot checked, throughput was down ~90% and p95 went from ~40ms to >1s, because more time was being spent on "background" GC than actually servicing requests. Hope that didn't come off adversarial. I just find GC fascinating, and ended up spending a bunch of time working with the team that owns those defaults to draft general recommendations. TLDR is that when in doubt don't specify/let the JVM pick for you, and don't be surprised if it picks serial :) | ||||||||
| ||||||||