Alex Rivera | Logout

Java's Serial garbage collector performing far better than other garbage collectors?

Asked 2012-03-16T14:16:35.503
13

I'm testing an API, written in Java, that is expected to minimize latency in processing messages received over a network. To achieve these goals, I'm playing around with the different garbage collectors that are available.

I'm trying four different techniques, which utilize the following flags to control garbage collection:

1) Serial: -XX:+UseSerialGC

2) Parallel: -XX:+UseParallelOldGC

3) Concurrent: -XX:+UseConcMarkSweepGC

4) Concurrent/incremental: -XX:+UseConcMarkSweepGC -XX:+CMSIncrementalMode -XX:+CMSIncrementalPacing

I ran each technique over the course of five hours. I periodically used the list of GarbageCollectorMXBean provided by ManagementFactory.getGarbageCollectorMXBeans() to retrieve the total time spent collecting garbage.

My results? Note that "latency" here is "Amount of time that my application+the API spent processing each message plucked off the network."

Serial: 789 GC events totaling 1309 ms; mean latency 47.45 us, median latency 8.704 us, max latency 1197 us

Parallel: 1715 GC events totaling 122518 ms; mean latency 450.8 us, median latency 8.448 us, max latency 8292 us

Concurrent: 4629 GC events totaling 116229 ms; mean latency 707.2 us, median latency 9.216 us, max latency 9151 us

Incremental: 5066 GC events totaling 200213 ms; mean latency 515.9 us, median latency 9.472 us, max latency 14209 us

I find these results to be so improbable that they border on absurd. Does anyone know why I might be having these kinds of results?

Oh, and for the record, I'm using Java HotSpot(TM) 64-Bit Server VM.

Edit
Report

2 Answers

2

There was an excellent talk by a Twitter engineer at the 2012 QCon Conference on this topic - you can watch it here.

It discussed the various "generations" in the Hotspot JVM memory and garbage collection (Eden, Survivor, Old). In particular note that the "Concurrent" in ConcurrentMarkAndSweep only applies to the Old generation, i.e. objects that hang around for a while.

Short-lived objects are GCd from the "Eden" generation - this is cheap, but is a "stop-the-world" GC event regardless of which GC algorithm you have chosen!

The advice was to tune the young generation first e.g. allocate lots of new Eden so there's more chance for objects to die young and be reclaimed cheaply. Use +PrintGCDetails, +PrintHeapAtGC, +PrintTenuringDistribution... If you get more than 100% survivor then there wasn't room, so objects get quickly promoted to Old - this is Bad.

When tuning for the Old generatiohn, if latency is top priority, it was recommended to try ParallelOld with auto-tune first (+AdaptiveSizePolicy etc), then try CMS, then maybe the new G1GC.

answered 2012-03-16T14:40:33.627
0

You can not say one GC is better than the other. it depends on your requirements and your application.

but if u want to maximize throughput and minimize latency: GC is your enemy! you should not call GC at all and also try to prevent JVM from calling GC.

go with serial and use object pools.

answered 2012-03-16T14:32:08.643

Your Answer