Friday, September 14, 2012

HotSpot Performance Option — SurvivorRatio

As shown in [1], -XX:SurvivorRatio has been classified as a performance option on HotSpot VM.

In this article, we will discuss how this option works and how it can impact an application's performance.

Survivor Spaces


The young generation space in all HotSpot garbage collectors is subdivided into an eden space and two survivor spaces.  Eden space is where new Java objects are allocated.  One of the survivor spaces is labeled the “from” survivor space, and the other survivor space is labeled the “to” survivor space.

If during a minor garbage collection, the “to” survivor space is not large enough to hold all of the live objects being copied from the eden space and the “from” survivor space, the overflow will be promoted to the old generation space. Overflowing into the old generation space may cause the old generation space to grow more quickly than desired and result in an eventual stop-the-world compacting full garbage collection.

If you are interested to learn more on garbage collector, read this excellent book— "Java Performance."


-XX:SurvivorRatio


For the following discussions, we will use the following HotSpot command options:
  • -server -Xms2560m -Xmx2560m -Xmn512m -XX:SurvivorRatio=4
In other words, we have set Young Generation size to be 512MB and the Survivor Ratio to be 4.  Since we didn't specify which Garbage Collector to be used, the default GC (i.e., -XX+UseParallelGC ) is selected.

When you set the SurvivorRatio to be 4, it means that:
  • The ratio of eden/survivor space size will be 4. The default value is 8.
Below we will see how the setting of SurvivorRatio will impact the sizes of  survivor spaces.

If InitialSurvivorRatio or MinSurvivorRatio were not specified, but the SurvivorRatio has been set, their values will be set to:
  • SurvivorRatio + 2
Then the calculation is as follows (Note that young_gen_size is the value specified with -Xmn):

  size_t survivor_size = young_gen_size / InitialSurvivorRatio;
  eden_size = size - (2 * survivor_size);


So, for SurvivorRatio = 4, different spaces are derived as follows:

 InitialSurvivorRatio = SurvivorRatio + 2 = 6
 survivor_size = 512m / 6 = 87360K  (Note that young_gen_size = 512m)
 eden = young_gen_size - 2 * survivor_size = 512m - 2 *  87360K  = 349568K
 young_gen_total(as reported in the gc print below) = eden + 1*survivor = 436928K

How to Verify?


When we started the application, we have specified the following GC-related print options:
  • -Xloggc:/<your_path>/logs/gc_0.log -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintReferenceGC 

After the application (i.e., a benchmark in our case) ends, you can find the following printouts at the end of gc_0.log:

Heap
PSYoungGen total 436928K, used 64296K [0x00000007e0000000, 0x0000000800000000, 0x0000000800000000) 
  eden space 349568K, 15% used [0x00000007e0000000,0x00000007e3571608,0x00000007f5560000)
  from space 87360K, 10% used [0x00000007f5560000,0x00000007f5eb8cd0,0x00000007faab0000)
  to space 87360K, 0% used [0x00000007faab0000,0x00000007faab0000,0x0000000800000000)
ParOldGen total 2097152K, used 1457708K 
[0x0000000760000000, 0x00000007e0000000, 0x00000007e0000000) 
  object space 2097152K, 69% used [0x0000000760000000,0x00000007b8f8b2a8,0x00000007e0000000)
PSPermGen total 393216K, used 246405K 
[0x0000000748000000, 0x0000000760000000, 0x0000000760000000) 
  object space 393216K, 62% used [0x0000000748000000,0x00000007570a14c0,0x0000000760000000)

As you can see it:
  • eden space / from space = 349568K / 87360K = 4
  • PSYoungGen total =  349568K +  87360K = 436928K

Why It's a Performance Option?


Given there is limited physical memory, you can increase heap to a certain limited size.  After that, you can tune survivor ratio to see if short lived objects can be allowed a longer time period to die in the young generation  (or if they can be promoted less directly into the old generation), which could help overall response time.

Bottom line: larger survivor spaces allow short lived objects a longer time period to die in the young generation and this helps application's response time (in other words, there will be less long-paused full garbage collections).

Acknowledgement


Some of the writings here are based on the feedback from Jon Masamitsu and Scott Oaks. However, the author would assume the full responsibility for the content himself.

References

  1. Java HotSpot VM Options
  2. The Fault with Defaults
  3. Garbage Collector Ergonomics
  4. Java Performance by Charlie Hunt and Binu John

No comments: