What are the necessary steps in getting a optimized value of Xms/Xmx/XX:MaxPermSize
?
Definitely I can set a large value but as you know GC take time in large memory. What are the general recommendation when I can spare the time in testing and finding these value?
For example, is the following figures help?
Eden Space heap usage - 42MB / 62MB (used / committed)
Survivor Space heap usage - 8.5MB / 8.5MB (used / committed)
CMS Old Gen heap usage - 100MB / 217MB (used / committed)
Non-heap memory pool usage - 36MB
The general rule is that you should not change the JVM memory settings before you have discovered a problem that need to be solved. The JVM does a pretty good job in tuning most parameters in runtime to suit your application.
If you have discovered a need to optimize the memory parameters it depends on what you need to optimize. The settings you would use would vary greatly depending on which aspect you need to optimize (for example settings for minimizing pauses are very different from settings that maximize throughput).
If you really do need to optimize, please provide more information on what aspect you need to optimize.
When tuning GC, you need to collect the GC statistics over a longer period of time and then act on that. Just one snapshot of Generation size is not enough.
You should:
Enable Full GC logging. Lightweight yet powerful.
- Use
-XX:+PrintTenuringDistribution -XX:+UnlockDiagnosticVMOptions -XX:+LogVMOutput -XX:LogFile=jvm.log -XX:+HeapDumpOnOutOfMemoryError -Xloggc:gc.log -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -showversion
Consider additional means of collecting information about your GC. Logging is fine but there are sometimes available lightweight command-line tools that will give you even more insight. Eg. jstat
for Hotspot which will show you occupation/capacity of Eden, Survivor and Old Gen.
Compute:
- Live Data Set, Allocation Rate, and Promotion Rate. This will tell you if you need a bigger Heap or if your eg. Young Gen is too small, or if your Survivor spaces are overflowing, etc.
- total GC time, it should be <5% of total running time. This way you can judge if your overall GC strategy works well.
- observe Perm Gen occupation
Once you have this data, you can start sizing the Generations and again monitor the impact of the changes you make. The usual sizing recommendations for throughput are:
- Old Gen = 1.5-2x of Live Data Set - your data set should comfortably fit into the OldGen space.
- Perm Gen = 1.5x of usual PermGen occupation.
- Young Gen = based on Allocation Rate. See how much you allocate in a second, then look at Promotion rate, reduce the promotion rate by increasing the YoungGen.
- Survivor Spaces = monitor Tenuring threshold and Promotion rate.
In general, sizing recommendations depend on the goal of your tuning:
- Throughput Tuning - see above,
- Low Latency Tuning - monitor the GC pauses
- Young GC too long => decrease young gen
- Young GC too frequent => increase young gen
- Footprint Tuning - adjust the sizes according the LiveDataSet, Promotion Rate and Allocation Rate. You may not need to add the extra room for each space as in the Throughput Tuning
See also the GC tuning question: Is there a cookbook guide for GC problems?
Ih the rare cases where i need to adjust those values there is a program called JavaVisualVM which is included in the jdk (bin folder i think) which i find very useful. You can connect to your running vm and analyze all its runtime parameters.
Under the "plugins" section you can also find a very useful plugin for monitoring the gc where you can see what exactly is going on in there.