|Skip Navigation Links|
|Exit Print View|
|Oracle Identity Analytics System Administrator's Guide 11g Release 1|
This section discusses tuning the Java Runtime Environment for optimum performance.
Version 5.0 of Java 2 Platform, Standard Edition (J2SE® platform) provides two implementations of the Java HotSpot® virtual machine:
The client VM is tuned for reducing startup time and memory footprint. Invoke it by using the -client JVM® command-line option.
The server VM is designed for maximum program execution speed. Invoke it by using the -server JVM command-line option.
By default, the application server uses the Virtual Machine for the Java Platform (JVM machine) setting appropriate to the purpose:
The Developer Profile, targeted at application developers, uses the -client JVM flag to optimize startup performance and conserve memory resources.
The Enterprise Profile, targeted at production deployments, uses the default JVM startup mode. By default, the application server uses the Java HotSpot client virtual machine. However, if an application server VM is needed, it can be specified by creating a <jvm-option> named -server.
You can override the default by changing the JVM settings in the Admin Console under Configurations > Config-name > JVM Settings (JVM Options).
The efficiency of any application depends on how well memory and garbage collection are managed. The following sections provide information on optimizing memory and allocation functions:
Garbage collection (GC) reclaims the heap space previously allocated to objects no longer needed. The process of locating and removing the dead objects can stall any application and consume as much as 25 percent throughput.
Almost all Java runtime environments come with a generational object memory system and sophisticated GC algorithms. A generational memory system divides the heap into a few carefully sized partitions called generations. The efficiency of a generational memory system is based on the observation that most of the objects are short-lived. As these objects accumulate, a low memory condition occurs forcing GC to take place.
The heap space is divided into the old generation and the new generation. The new generation includes the new object space (eden) and two survivor spaces. The JVM allocates new objects in the eden space, and moves longer-lived objects from the new generation to the old generation.
The young generation uses a fast copying garbage collector that employs two semi-spaces (survivor spaces) in the eden, copying surviving objects from one survivor space to the second. Objects that survive multiple young space collections are tenured, meaning they are copied to the tenured generation. The tenured generation is larger and fills up less quickly. So, it is garbage collected less frequently, and each collection takes longer than a young-space-only collection. Collecting the tenured space is also referred to as doing a full generation collection.
The frequent young space collections are quick (a few milliseconds), while the full generation collection takes longer (tens of milliseconds to a few seconds, depending upon the heap size).
Other GC algorithms, such as the Concurrent Mark Sweep (CMS) algorithm, are incremental. They divide the full GC into several incremental pieces. This provides a high probability of small pauses. This process comes with an overhead and is not required for enterprise web applications.
The two primary measures of garbage collection performance are throughput and pauses. Throughput is the percentage of the total time spent on other activities apart from GC. Pauses are times when an application appears unresponsive due to GC.
Two other considerations are footprint and promptness. Footprint is the working size of the JVM process, measured in pages and cache lines. Promptness is the time between when an object becomes dead and when the memory becomes available. This is an important consideration for distributed systems.
A particular generation size makes a trade-off between these four metrics. For example, a large young generation likely maximizes throughput, but at the cost of footprint and promptness. Conversely, using a small young generation and incremental GC will minimize pauses, and thus increase promptness, but decrease throughput.
JVM diagnostic output will display information on pauses due to GC. If you start the application server in verbose mode using the command asadmin start-domain -verbose domain, then the command-line argument -verbose:gc prints information for every collection.
Here is an example of output of the information generated with this JVM flag:
[GC 50650K->21808K(76868K), 0.0478645 secs] [GC 51197K->22305K(76868K), 0.0478645 secs] [GC 52293K->23867K(76868K), 0.0478645 secs] [Full GC 52970K->1690K(76868K), 0.54789968 secs]
On each line, the first number is the combined size of live objects before GC, the second number is the size of live objects after GC, and the number in parentheses is the total available space, which is the total heap size minus one of the survivor spaces. The final figure is the amount of time that the GC took. This example shows three minor collections and one major (full) collection. In the first GC, 50650 KB of objects existed before collection and 21808 KB of objects existed after collection. This means that 28842 KB of objects were dead and collected. The total heap size is 76868 KB. The collection process required 0.0478645 seconds.
Other useful monitoring options include:
-XX:+PrintGCDetails for more detailed logging information
-Xloggc:file to save the information to a log file
For applications that do not dynamically generate and load classes, the size of the permanent generation affects GC performance. For applications that dynamically generate and load classes (for example, JSP applications), the size of the permanent generation does affect GC performance because filling the permanent generation can trigger a full GC. Tune the maximum permanent generation with the -XX:MaxPermSize option.
This section discusses topics related to tuning the Java heap size for performance:
Maximum heap size depends on the maximum address space per process.
Maximum heap space is always smaller than the maximum address space per process because the process also needs space for stack, libraries, and so on. To determine the maximum heap space that can be allocated, use a profiling tool to examine the way memory is used. Gauge the maximum stack space that the process uses and the amount of memory taken up by libraries and other memory structures. The difference between the maximum address space and the total of those values is the amount of memory that can be allocated to the heap.
You can improve performance by increasing the heap size or by using a different garbage collector. In general, for long-running server applications, use the J2SE throughput collector on machines with multiple processors (-XX:+AggressiveHeap) and as large a heap space as you can fit in the free memory of your machine.
The recommended Java heap size for the Oracle Identity Analytics application is discussed in the following section.
You can control the heap size with the following JVM parameters:
The -Xms and -Xmx parameters define the minimum and maximum heap sizes, respectively. Since garbage collection occurs when the generations fill up, throughput is inversely proportional to the amount of memory available. By default, the JVM grows or shrinks the heap at each garbage collection to try to keep the proportion of free space to the live objects at each collection within a specific range. This range is set as a percentage by the parameters -XX:MinHeapFreeRatio=minimum and -XX:MaxHeapFreeRatio=maximum, and the total size bounded by -Xms and -Xmx.
Set the values of -Xms and -Xmx equal to each other for a fixed heap size. When the heap grows or shrinks, the JVM must recalculate the old and new generation sizes to maintain a predefined NewRatio.
The NewSize and MaxNewSize parameters control the new generation's minimum and maximum sizes. Regulate the new generation size by setting these parameters to the same value. The bigger the younger generation, the less often minor collections occur. The size of the young generation relative to the old generation is controlled by NewRatio. For example, setting -XX:NewRatio=3 means that the ratio between the old and young generation is 1:3, and the combined size of eden and the survivor spaces will be fourth of the heap.
By default, the application server is invoked with the Java HotSpot server virtual machine. The default NewRatio for the Server VM is 2: the old generation occupies 2/3 of the heap while the new generation occupies 1/3. The larger new generation can accommodate many more short-lived objects, decreasing the need for slow major collections. The old generation is still sufficiently large enough to hold many long-lived objects.
To size the Java heap:
Decide the total amount of memory you can afford for the JVM. Accordingly, graph your own performance metric against young generation sizes to find the best setting.
Make plenty of memory available to the young generation. The default is calculated from NewRatio and the -Xmx setting.
Larger eden or younger generation spaces increase the spacing between full garbage collections. But young space collections could take a proportionally longer time. In general, keep the eden size between one fourth and one third the maximum heap size. The old generation must be larger than the new generation.
This is an example heap configuration used by Oracle Identity Analytics on GlassFish (RedHat Linux 64-bit) for a large role consolidation and entitlements discovery application: -Xms2048m -Xmx2048m