Java 9 GC

The new default collector in Java 9 is G1. This is bad, because G1 is hopelessly slow and everything runs like it’s going through treacle.
Can anyone recommend a set of commandline magic parameters that mimics good ol’ -Xincgc?

Cas :slight_smile:

Wtf it looks like they removed ALL garbage collectors other than G1?

It would be useful to see a simple test program that demonstrates bad performance with G1GC. It certainly makes an interesting set of tradeoffs, but I haven’t seen an application where enabling G1GC has such a pronounced impact on performance.

Cas, would you be able to post such a program?

Unfortunately not - all I can tell you is that it halves the framerate of Battledroid, and Eclipse seems to almost grind to a halt under Java 9.
(All 64-bit stuff, compressed OOPS)

Cas :slight_smile:

More good reasons to stick with the Java 8 LTS for a while! :wink:

Still, -Xincgc is kind of still there, if you can find documentation of what it actually translated to (got a note somewhere I’ll see if I can dig out). See https://docs.oracle.com/javase/9/gctuning/concurrent-mark-sweep-cms-collector.htm

I did read on the OpenJDK list a bunch of people (inc. Google and Red Hat people IIRC) talking about undeprecating and improving CMS - think Oracle are happy for that if they don’t have to do anything.

Could you describe what Battledroid’s doing in the hot path? Are there many allocations? Are there many reference writes (e.g. a BVH getting updated)? This could be a matter of replacing OO code with something more data oriented.

@Spasi - it’s been quite a long time since I really delved into it in any depth. The point being though that simply changing the garbage collector to -Xincgc doubled my framerate and the amount of garbage I was generating was already quite modest really. I did in the end even have to do something data oriented just to get my A* stuff working fast enough - instead of allocating and forgetting tens of thousands of A* “Nodes”, I instead used large expanding arrays of int[] instead, effectively mostly managing my own memory… crap.

@Nsigma - thanks for the link (obviously, it’s Googlable, but it’s good to have it recorded here for posterity) - I guess I’ll try each combo out in turn to find out what’s best for my usage.

Cas :slight_smile:

Really annoying, that the said to be best Garbage Collector seems to perform worse for games.

@princecc: Would you mind take a look at your app with JMC and show us some metrics comparing the old state and the state after your latest changes? I found some comparisons in the internet, where G1 reduced the max pause time while keeping avg pause time equivalent to cms. Maybe you could post the gc times and avg pauses, created objects (screenshots) etc here, I’m just curious :slight_smile:

Currently not really up to speed on the project, being diverted. I will return to it in the next few months but will likely mention the issue again around then, as it is vexing.
I am particularly keen to try the Shenandoah GC which as I understand it is available in the OpenJDK builds.

Cas :slight_smile:

That’s interesting. I thought that Shenandoah is not suitable for normal applications, as the official description states:

This is not the one GC to rule them all. If you are running with a heap of 20GB or less or if you are running with a single core, you are probably better off with one of the current GC algorithms.

Looking forward to your results.

We’re reasonably multithreaded in some places but the heap is definitely much smaller (under 1GB). What interested me was its consistency and high speed. Maybe the serial GC is all I really need though.

Cas :slight_smile:

If you’re looking to test Shenandoah on Windows, looks like it’s available in the 1.8.0.151 ojdkbuild.

[quote=“h.pernpeintner,post:10,topic:59143”]
(Low-)pause-less GCs sacrifice maximum throughput for lower latency/pauses. Shenandoah has lower throughput than G1GC, but significantly lower pauses. A real-time game would actually value low latency much more than high throughput. Afaik, Shenandoah has been shown to perform well on small heaps too. Also note that Shenandoah increases object size (Brooks pointers).

[quote=“princec,post:11,topic:59143”]
We have apps in production capped to 512MB with SerialGC and pauses are indeed small enough that it’s a good tradeoff.

@princec found an old launcher with this in it, which I think is similar/same as -incgc


-J-XX:+UseConcMarkSweepGC -J-XX:+CMSIncrementalMode -J-XX:+CMSIncrementalPacing

However, it looks like while CMS is still there, they’ve also removed the incremental pacing flags. Maybe just try the first argument?

That’s a good point. I’ve been using the SerialGC more recently. If you can keep the heap from growing too much it’s OK. In Praxis LIVE I have the ability to split off pipelines into child VMs - I run audio in a separate VM with SerialGC and low heap size, but then I guess my “fps” is 10x what you need! :wink:

Why not using adoptopenjdk.net instead?

So glad I switched over to C/C++

Is Shenandoah in there? Website claims not but didn’t find release notes quickly.

Thanks @Archive for the drive-by trolling! :stuck_out_tongue:

I have to use C at work every day… it’s like trying to build the Taj Mahal out of matchsticks.

Cas :slight_smile:

Is it still true about Java 9 GC? or it was improved since post creation time?

Not sure I’d be worrying about anything other than Java 11 GC. But it remains to be seen if that is any better.

Now, interestingly since this thread was active, I had someone contribute a small patch to my Java JACK bindings (a native real-time callback-based audio server). I haven’t tried Shenandoah myself, but they were getting reliable ~1ms latency with no xruns (missed deadlines) using the bindings with Shenandoah. If that proves to be the case in general performance, it could be the ideal GC for games, despite what is quoted above.

Wow. I have no idea what you just said. Lol. I have a lot to learn!