0

I have a Java application that normally has very healthy garbage collection statistics. A tenured collection normally happens every hour or so and the STW portions take just fractions of a second. But strangely a collection always happens within about the first five minutes of app startup. This is a real problem because at that time, CPU usage is already much higher than normal (due to increased network calls that eventually get cached), so these pauses are always longer than normal and even run past 8 seconds if I'm doing a restart under extremely heavy load.

Here are the JVM args:

-Xms4096m 
-Xmx4096m 
-XX:PermSize=768m 
-XX:MaxPermSize=768m 
-XX:SurvivorRatio=6 
-XX:NewSize=1024m 
-verbose:gc 
-XX:-DisableExplicitGC 
-XX:+PrintGCDetails 
-XX:+PrintGCApplicationStoppedTime 
-XX:+PrintGCTimeStamps 
-XX:+PrintHeapAtGC 
-XX:+PrintTenuringDistribution 
-XX:+HeapDumpOnOutOfMemoryError 
-XX:MaxDirectMemorySize=2048m 
-XX:+UseConcMarkSweepGC 
-XX:+CMSClassUnloadingEnabled 
-XX:+PrintConcurrentLocks 
-XX:+ExplicitGCInvokesConcurrent 

The question here is what triggers this tenured collection since there is almost 2gb free in old gen when it occurs. Here's the usage under normal circumstances right before a tenured collection:

concurrent mark-sweep generation total 3145728K, used 2897098K 

And here's the usage just before a tenured collection is triggered within the first few minutes of startup:

concurrent mark-sweep generation total 3145728K, used 1573655K 

My understanding is that a tenured collection should only occur when old gen is nearly full; what could trigger it otherwise?

Cameron
  • 1,868
  • 3
  • 21
  • 38

1 Answers1

1

A key concept of the CMS is that it should start collecting before you run out of space, thus allowing it to run concurrently. If it waited until you ran out it would trigger a serial stop the world collection.

For this reason there is two thresholds to determine when to trigger a collection prematurely.

-XX:CMSInitiatingOccupancyFraction=90 (by default)
-XX+UseCMSInitiatingOccupancyOnly

If you don't set these, it will work out when it a good time to start using "metrics"

My understanding is that a tenured collection should only occur when old gen is nearly full;

This is what the Parallel Collector does.

Peter Lawrey
  • 525,659
  • 79
  • 751
  • 1,130
  • 1
    Thanks for your response. Are you saying that the JVM doesn't know how long the tenured collection will take, so it starts it unnecessarily early the first time? I understand not waiting until it's actually full, but in my case it's barely half full. And if that's the case, will setting those two flags force the JVM to wait until old gen is 90% full before doing the first tenured collection? – Cameron Sep 29 '14 at 19:51
  • @Cameron That is what it should do, yes. I tend to make the eden size very large, e.g. 24 GB and then the tenure space is simple to tune ;) – Peter Lawrey Sep 29 '14 at 19:54
  • you set your eden to 24gb...so you never hit a full GC because everything stays in young gen? – Cameron Sep 29 '14 at 20:16
  • Actually I never hit a minor collection as I use off heap most of the time so it takes a day to fill the Eden space. This might only make sense for HFT ;) I run a full gc every night, the only GC all day. – Peter Lawrey Sep 30 '14 at 06:50