top | item 35197810

(no title)

ordx | 3 years ago

Is there a good decision flowchart on how to chose GC for a particular task/application?

discuss

order

exabrial|3 years ago

Always start with the question, do you need to optimize? :) Most likely, Probably not! Java is _fast_, and the JVM is pretty good at what it does; 95% of the time merely checking for GC thrashing is all that’s needed.

Otherwise, start with G1 and get your Xmx value in the ballpark. VisualVm can help you determine if you're thrashing. Are you GCing like 10+ times per second? Keep an eye on it. If you start hitting giant pause times and 50+ collections a second, you've got problems :) Increase Xmx. (and no, please don't set Xms = Xmx).

If you have issues past that, it’s not the garbage collector that needs help; the next step is to audit your code base. Bad code makes any Garage Collector in any language to misbehave.

For instance, are you `select *`ing from a table then using the Java streams api to filter rows back from a database? That will cause GC issues :) fix that first.

So now if you've got to this point and you still need to optimize, what we've done is just run through the different collectors under load. One of our JVMs is a message broker (ActiveMQ 5.16.x) and we push a couple thousand messages per second through it. We found that Shenandoah actually improved latency for our particular use case, which was more important that throughput and outright performance.

Oh, and if your application and usecase is _extremely_ sensitive to latency, forget everything I wrote and contact Azul systems about their Prime collector. They're pretty awesome folks.

Szpadel|3 years ago

do you mind explaining to someone that does not do any java dev, but operates some java servers (like elasticsearch, etc) what's wrong with Xms = Xmx?

And what is better strategy to set it?

pojzon|3 years ago

And if you do any IO with bytebuffers or library that does that -> you simply gonna have a bad time with native memory usage which is 10x as convoluted as selecting GC and carring only about the heap.

And best part, every month there is a new bug released in regards to NMT reporting stupid memory usage that is hard to track coz regular metrics dont expose it.

So you have to enable NMT which in most cases is a straight 5-10% performance degradation.

And for latency use ZGC or Shanondoah.

And dont forget 50 jvm flags to tweak memory usage of various parts of memory that can negatively impact your production like caches, symbol tables, metaspace, thread caches, buffer caches and other.

God I hate that so much. Just let me set one param for memory and lets be over with it.

vips7L|3 years ago

Oracle has an overview here [0]. But in general I would say unless you're facing an issue just to let the JVM pick the GC and only really tune -Xmx

[0] https://docs.oracle.com/en/java/javase/18/gctuning/introduct...

colechristensen|3 years ago

Yup, every once in a while use the various available tools to watch your memory usage patterns and how GC runs. If it looks fine continue to leave it as is.

brucethemoose2|3 years ago

I think generational ZGC is going to be the "sane default" soon.

marginalia_nu|3 years ago

Eh, there's probably always going to be a different answer depending on whether you prioritize latency vs throughput.

popfalushi|3 years ago

Default gc depends on how many cpus and ram vm has. With 1 core it is always serialgc, for example. 2 cores and less than 4 gb - concurrent mark and sweep IIRC. G1GC starts a bit later.

re-thc|3 years ago

Would be good to have more benchmarks and articles on G1 vs ZGC once that happens.

the8472|3 years ago

single-core, latency doesn't matter, low footprint: serial

throughput: parallel or G1

balance between latency, footprint and throughput: G1

latency more important than throughput or footprint: ZGC or shenandoah

missiles and HFT: Epsilon