Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why Go can lower GC pauses to sub 1ms and JVM has not?

So there's that: https://groups.google.com/forum/?fromgroups#!topic/golang-dev/Ab1sFeoZg_8:

Today I submitted changes to the garbage collector that make typical worst-case stop-the-world times less than 100 microseconds. This should particularly improve pauses for applications with many active goroutines, which could previously inflate pause times significantly.

High GC pauses are one of the things JVM users struggle with for a long time.

What are the (architectural?) constraints which prevent JVM from lowering GC pauses to Go levels, but are not affecting Go?

like image 983
mabn Avatar asked Oct 29 '16 10:10

mabn


People also ask

How do I reduce GC pauses?

If your application's object creation rate is very high, then to keep up with it, the garbage collection rate will also be very high. A high garbage collection rate will increase the GC pause time as well. Thus, optimizing the application to create fewer objects is THE EFFECTIVE strategy to reduce long GC pauses.

What causes JVM pauses?

A garbage collection pause, also known as a stop-the-world event, happens when a region of memory is full and the JVM requires space to continue. During a pause all operations are suspended.

What is GC pause time in Java?

Metronome garbage collector (GC) pause time can be fine-tuned for each Java™ process. By default, the Metronome GC pauses for 3 milliseconds in each individual pause, which is known as a quantum.

Is GC part of JVM?

Java garbage collection is an automatic process. The programmer does not need to explicitly mark objects to be deleted. The garbage collection implementation lives in the JVM. Each JVM can implement garbage collection however it pleases; the only requirement is that it meets the JVM specification.


1 Answers

2021 Update: With OpenJDK 16 ZGC now has a max pause time of <1ms and average pause times 50µs

It achieves these goals while still performing compaction, unlike Go's collector.

Update: With OpenJDK 17 Shenandoah exploits the same techniques introduced by ZGC and achieves similar results.


What are the (architectural?) constraints which prevent JVM from lowering GC pauses to golang levels

There aren't any fundamental ones as low-pause GCs have existed for a while (see below). So this may be more a difference of impressions either from historic experience or out-of-the-box configuration rather than what is possible.

High GC pauses are one if the things JVM users struggle with for a long time.

A little googling shows that similar solutions are available for java too

  • Azul offers a pauseless collector that scales even to 100GB+
  • Redhat is contributing shenandoah to openjdk and oracle zgc.
  • IBM offers metronome, also aiming for microsecond pause times
  • various other realtime JVMs

The other collectors in openjdk are, unlike Go's, compacting generational collectors. That is to avoid fragmentation problems and to provide higher throughput on server-class machines with large heaps by enabling bump pointer allocation and reducing the CPU time spent in GC. And at least under good conditions CMS can achieve single-digit millisecond pauses, despite being paired with a moving young-generation collector.

Go's collector is non-generational, non-compacting and requires write barriers (see this other SO question), which results in lower throughput/more CPU overhead for collections, higher memory footprint (due to fragmentation and needing more headroom) and less cache-efficient placement of objects on the heap (non-compact memory layout).

So GoGC is mostly optimized for pause time while staying relatively simple (by GC standards) at the expense of several other performance and scalability goals. JVM GCs make different tradeoffs. The older ones often focused on throughput. The more recent ones achieve low pause times and several other goals at the expense of higher complexity.

like image 138
the8472 Avatar answered Sep 22 '22 18:09

the8472