Hitachi

uCosminexus Application Server System Design Guide


7.6.1 Estimating the memory size of the Survivor area in Java heap

Tune the memory size of the Survivor area while checking the usage of the Survivor area, by actually running the application.

The flow of tuning is as follows:

  1. Estimate the memory size used for the request and response processing in the application, and specify this memory size in the memory size of the Survivor area, and then execute the application.

    At this point, to output the information used for tuning, specify the -XX:+HitachiVerboseGCPrintTenuringDistribution option and invoke the J2EE server.

  2. Check the memory usage based on the memory size allocated to the Survivor area and the actual memory usage when the application is running.

    When the memory usage approaches 100%, there is no longer enough space for in-use objects in the New area and the From space of the Survivor area to enter the To space when copy GC is executed. The objects are saved to the Tenured area instead. In such a case, consider increasing the Survivor area.

  3. Check the age distribution of the objects of the Survivor area.

    If you increase the memory size of the Survivor area and threshold value required for promoting, it leads to delay in promoting the objects. Storing the objects with a long lifespan continuously in the Survivor area causes deterioration in the performance. On the other hand, if you reduce the memory size of the Survivor area, and reduce the threshold value required for promoting, the object promoting becomes faster. However, promoting objects with short lifespans can cause Full GC to occur more frequently.

    In such a case, consider balancing both the memory size of the Survivor area, and the threshold value for promoting the objects.

The respective tuning operations are explained below:

Organization of this subsection

(1) Estimating the memory size used in the request and response processing

The Survivor area stores the objects with a short lifespan. In case of applications running on the server side, the Survivor area can be considered as an area that stores the objects with a short lifespan that are used for processing a request and response. As a result, for estimating the memory size of the Survivor area, consider the maximum size of objects with a short lifespan that exist at a certain point, or in other words, consider the maximum size of the memory used for processing a request and response, at a certain point of time. For example, in case of an application configured with stateless servlets, the memory size of the Survivor area can be considered as the-maximum-memory-size-used-for-processing-one-request × the-number-of-concurrent-executions-of-the-request.

(2) Checking the memory usage

Set the value that is estimated from (1) Estimating the memory size used in the request and response processing, as the memory size of the Survivor area, and then execute the application. Check the memory usage for memory size allocated to the Survivor area from the memory usage at runtime.

Reference note

You cannot directly specify the memory size of the Survivor area.

To specify the memory size of the Survivor area, you must first specify the maximum size of Java heap by the -Xmx option, then use the -XX:NewRatio=value option to specify ratio that divides the memory size of Java heap into the New area and the Tenured area, and finally specify the ratio with respect to the Eden area, by the -XX:SurvivorRatio=value option.

You can check the memory usage with the extended verbosegc information.

The following example of output shows the extended verbosegc information for copy GC at runtime:

...
[VGC]Wed May 11 23:12:05 2005[GC 27340K->27340K(32704K), 0.0432900 secs][DefNew::Eden: 3440K->0K(3456K)][DefNew::Survivor: 58K->64K(64K)][Tenured: 23841K->27282K(29184K)][Metaspace: 3634K(4492K, 4492K)->3634K(4492K, 4492K)][class space: 356K(388K, 388K)->356K(388K, 388K)][cause:ObjAllocFail][User: 0.0156250 secs][Sys: 0.0312500 secs]
...

DefNew::Survivor: 58K->64K(64K) means memory-size-before-GC-execution -> memory-size-after-GC-execution (allocated-memory-size). In this case, 64 KB is already in use in the Survivor area of 64 KB, and therefore, the usage becomes 100%. This indicates insufficient memory size of the To space in copy GC, and the Java object is saved. This save process stores an object with a short lifespan that is not meant to be stored in the Tenured area, causing Full GC to occur more frequently. In such a case, consider increasing the memory size of the Survivor area. Estimate the memory size of the new Survivor area in the following manner:

Memory-size-of-the-new-Survivor-area
= memory-size-of-the-existing-Survivor-area + total-size-of-the-saved-Java-object

The total-size-of-the-saved-Java-object can be approximated with the increased memory size of the Tenured area after the GC is executed. For example, Tenured: 23841K->27282K(29184K) indicates the increased memory size of the Tenured area, and becomes 27,282 KB - 23,841 KB =3,441 KB.

If you increase the memory size of the Survivor area, the threshold value required for promoting the Java objects increases, and thereby, the object promotion becomes difficult. For details, see (3) Checking and estimating the age distribution of objects. As a result, the number of Java objects that are not collected by copy GC increases and hence, estimate and setup the -XX:TargetSurvivorRatio=value in the following manner:

New -XX:TargetSurvivorRatio=<value>
= existing--XX:TargetSurvivorRatio=<value> × (memory-size-of-the-existing-Survivor-area-and-memory-size-of-the-new-Survivor-area)

(3) Checking and estimating the age distribution of objects

Check the age distribution of the objects of the Survivor area, and ensure that the objects with a long lifespan do not continue to exist, or the objects with a short lifespan are not being promoted. You can check the age distribution of objects with the help of the output results of the -XX:+HitachiVerboseGCPrintTenuringDistribution option.

If you specify the -XX:+HitachiVerboseGCPrintTenuringDistribution option in usrconf.cfg when invoking the J2EE server, the used state of the Survivor area is output to the Java VM log file when copy GC occurs. The output example is as follows:

[PTD]Wed May 28 11:45:23 2008[Desired survivor:5467547 bytes][New threshold:3][MaxTenuringThreshold:31][age1:1357527][age2:1539661]

Following the New threshold, the minimum age of the Java objects promoted by the next copy GC is output. In this example, the Java object whose age is 3 or more is promoted by the next copy GC. Following the age<numeric value>: is the total of memory size used by the Java objects, whose age is between one and that age in the Survivor area. In this example, if the memory size of the Java object with age 1 is 1,357,527 bytes, total 1,539,661 bytes of the memory size of both Java objects with age 1 and 2 is displayed. Also, it is concluded that the memory size of the Java object with age 2 is 182,134 (1,539,661-1,357,527) bytes if calculated back from the total. Generally, the age distribution of the object in the Survivor area is similar to the following graph:

Figure 7‒12: Age distribution of the objects in the Survivor area

[Figure]

The 'Size' in the graph is a total size of the Java object of a certain 'Age'. Also, the 'Total size' is a total size of the Java objects up to a certain 'Age'.

In this graph, the size that the Java object in the Survivor area occupies, decreases as the age increases. Also, the size that is reduced when age is increased by 1 year, becomes larger, as lesser the age, and based on this, the following conclusions are drawn:

In this example, the Java object with age 6 or above is hardly collected by the copy GC. If the threshold value for promoting a Java object is age 7 or greater, copy GC is applied to Java objects with a low probability of collection which reduces system performance. On the other hand, if the threshold value for the Java object promoting is less than age 2, the object having higher possibility of being collected by the copy GC can be promoted, and this causes increase in the occurrences of Full GC. In this example, the threshold value for promoting is between 5 to 6 age that implies a balanced threshold value.

The trend of the graph differs depending on the system, and therefore, you must check the age distribution of the objects in the Survivor area, and decide a suitable promoting age of the objects for each system.

Reference note

The threshold value for the Java object promoting changes dynamically for each copy GC, and is decided based on the -XX:MaxTenuringThreshold=value option, and the memory size of the Survivor area and the value set in the -XX:TargetSurvivorRatio=value option. The -XX:MaxTenuringThreshold=value option is the maximum age of the threshold value required for promoting. Whenever the age of the Java object exceeds this value, the Java objects are promoted without fail. The -XX:TargetSurvivorRatio=value option is a target value of the memory usage of the Survivor area. To set the memory usage of the Survivor area closer to the target value, the JavaVM decides the threshold value required for object promoting. Specifically, searches for n that indicates the target usage of the total size of Java object from age 1 to n when the copy GC is completed, and sets the threshold value for promoting in next copy GC, to n. The default value of -XX:TargetSurvivorRatio=value is 50%. If the memory usage of the Survivor area is greater, you can use the Survivor area more effectively, and therefore, it is easy to save the objects as the free space of the Survivor area is not available.