JVM and GC tuning - theory for no Full GC
I have large scale application with two type of objects: long living (cache) and short living (request-process-response). Theoretically, with this type of application, I think it is possible to configure Young vs Old spaces, so Old space consumption is constant, resulting in no Full GC.
I've changed newSize-maxNewSize params, but, Old heap continues to rise until Full GC. After each Full GC, consumption is down to 20% (cache takes 20%). For some reason, my objects gets into Old space. I have two suspects why are moved to Old space:
Per this article: http://chaoticjava.com/posts/gc-tips-and-memory-lea开发者_如何转开发ks/ it's told if you have big objects allocated, those go directly to Old space. Is this true, and if it is, is there JVM Option param that can set object size threshold for Young space?
If I understood the process correctly, objects are switched between To-From survival sections before are moved to Old section. Is there param that can set how many switches between To and From is to be done before moving to Old space?
Any other tips?
Thanks, Amar
It does sound like your survivor spaces are not big enough. You need to make them large enough that no objects need to be collected. An object is only switched into and out of survivor space once.
If you are allocating large objects, can you use an Object pool for them avoiding the need to GC them. Have you considered using an object pool for your request/process/response data as well? e.g. a simple one is to use a ThreadLocal.
Have you tried the G1 collector which is designed to progressively collect all your memory and reduce the big hit of a full GC.
Are you sure that the growth of the old generation is just not cached objects? Unless your cache is fixed and never changing, you're going to be continually adding to it. As objects that have made it to the old generation expire from that cache they're going to stay in memory until the next full GC.
I've had much better luck with the concurrent mark sweep collector to entirely eliminate long pauses from full GCs. It takes a bit of tuning and it can vary per application. Here's what we use to run a 24GB 64-bit JVM with sub-second GC pauses while serving 100+ page requests per second with large caches:
-Xms24g -Xmx24g -XX:+UseCompressedOops -XX:NewRatio=4 -XX:SurvivorRatio=8
-XX:+UseConcMarkSweepGC -XX:+UseParNewGC -XX:+DisableExplicitGC
-XX:+UseCMSInitiatingOccupancyOnly -XX:+CMSClassUnloadingEnabled
-XX:+CMSScavengeBeforeRemark -XX:CMSInitiatingOccupancyFraction=68
Is there param that can set how many switches between To and From is to be done before moving to Old space?
Yes, -XX:MaxTenuringThreshold
This switch determines how many times the objects hop between the "From" and "To" Survivor spaces before getting promoted to the older generation. The largest value is 15 for Java 6 and 31 for earlier JDKs. The default value is 15 for the parallel collector and is 4 for CMS collectors.
From the Sun JVM GC docs,
Use -XX:MaxTenuringThreshold=0 to move an object that survives a young generation collection immediately to the tenured generation.
As you want to do the opposite of that, if you haven't set this value it would be at the default, which is quite enough to decide whether the object does need to go into Old - provided as @Peter says, the survivors are large enough to hold those objects.
Whats your SurvivorRatio set at? And what's your total Heap?
Object life time characteristics play a critical role here.Important tuning knobs are size of survivor space, tenuring threshold and size of young generation. Strategically we want objects to die young, so if there is enough gap between minor collections lot of object will die in young generation. Besides we can configure the tenuring threshold so that the objects remain in survivor space for desired number of collections.
As we keep large number of live objects in the survivor space and keep copying them from one space to other for a number of minor GC it increases the cost of minor GC.
Keeping a large young generation naturally increases the gap between consecutive minor collections and gives more time to objects to die.
One can strike a right balance by experimenting with these variables to reduce the object promotions to old generation with a view on acceptable young generation pauses
精彩评论