Reputation: 9568
I'm trying to tune the GC such that it won't kick in during a short benchmark.
For that I tried to set the young generation as big as I can and made sure I create less garbage than the Eden size.
I used the following parameters:
java -Xmx1g -Xms1g -Xmn1g -XX:NewSize=1000m -XX:MaxNewSize=1g -XX:SurvivorRatio=10000 -verbose:gc Main
But for some reason I still see [Full GC] logs when the VM memory is only at 300M, is there any JVM tuning I'm missing?
Upvotes: 4
Views: 436
Reputation: 20065
Your survivor ration is very important, with 10 000 you are telling the JVM that a survivor space is one 10000th the size of eden.
If survivor spaces are too small, copying collection overflows directly into the tenured generation. If survivor spaces are too large, they will be uselessly empty. At each garbage collection the virtual machine chooses a threshold number of times an object can be copied before it is tenured. This threshold is chosen to keep the survivors half full. The command-line option -XX:+PrintTenuringDistribution can be used to show this threshold and the ages of objects in the new generation. It is also useful for observing the lifetime distribution of an application.
So obviously with a so low survivor space ratio, your objects are directly stored in the tenured generation.
When the tenured generation is full a major collection happened and that's why you see [Full GC...]
in the log.
If you want to make the young generation bigger use :
-XX:NewRatio=1
It means the combined size of the eden and survivor spaces will be one half of the total heap size. (I guess you can't have a bigger young generation)
Also you don't have to set -XX:NewSize
if you have already set -Xmn
, -Xmn
is the same thing since 1.4. And I guess you don't want to bound young gen from above with -XX:MaxNewSize
, the default value is unlimited. But setting the size of the young generation with the same value as the max heap size imply you don't let space for old generation so I guess the JVM will resize generations.
To conclude there is also some case where allocations can occur directly into the tenured generation. (Do objects ever get allocated directly into the old generation?)
- If an allocation fails in the young generation and the object is a large array that does not contain any references to objects, it can be allocated directly into the old generation. In some select instances, this strategy was intended to avoid a collection of the young generation by allocating from the old generation. The threshold size is 64k words.
Upvotes: 2
Reputation: 533880
You can get full GC because your tenured space has filled up (large objects are placed directly into tenured space)
I usually try an eden size of 4 - 24 GB but make sure tenured space is 0.5 to 2 GB in size.
Upvotes: 2
Reputation: 1024
The GC is still going to run if you're deallocating lot's of objects, it's not purely a matter of waiting until you have used all of the allocated space, if it did that it would lead to serious GC jitter on occasions when it did run.
You should be looking at your use of object handling and whether you could be more efficient. Take a look at the LMAX disrupter pattern for some ideas on how to use objects for reuse, by updating the object values, rather than deallocating an replacing the objects themselves.
That being said, this is a pretty good article on tuning the GC - http://developer.amd.com/documentation/articles/pages/4EasyWaystodoJavaGarbageCollectionTuning.aspx
Upvotes: 1