6 Tuning for Low Latencies

This chapter describes how to tune the Oracle JRockit JVM for low latencies.

Long latencies can make some applications experience poor performance even though the overall throughput is acceptable. For example, a transaction-based system might seem to execute a satisfactory number of transactions during a specified amount of time but still show some uneven behavior with transactions occasionally timing out, even on low loads. Latencies in the application or the environment in which the application is run might cause this uneven or poor performance. Latencies occur due to anything from contention in the Java code to slow network connections to a database server. Latencies can also be caused by the JVM (during garbage collection for example) depending on how the JVM is tuned.

This chapter includes information about the following topics:

6.1 Measuring Latencies

Application developers follow different methods to measure the performance of their application. You can, for example, run a set of simulated use cases and measure the time it takes to execute them, the number of a specific kind of transactions executed per minute, the average transaction time, or the percentage of the transaction time above or below a specific threshold. When you tune for low latencies, you are most interested in measuring the number of transaction times above a certain threshold. For best tuning results, you should have a varied set of benchmarks that are as realistic as possible and are run for a longer period of time. Twenty minutes is often a minimum; sometimes the full effect of the tuning can be seen only after several hours.

When you have identified a situation where the long latencies occur, you can start monitoring the JRockit JVM using some of the following methods:

  • Create a run-time analysis report by using the JRockit Flight Recorder supplied with the product. If you are running JRockit JVM and Oracle JRockit Mission Control, the individual pause times for each garbage collection pause (there can be several pauses during one garbage collection) are reported. The JRockit Flight Recorder report also shows page faults occurring during garbage collection. For information about creating and analyzing a JRockit Flight Recorder report, see the Oracle JRockit Mission Control Online Help.

  • You can create a latency recording to monitor the occurrences of latencies in your application. For more information about creating a latency recording, see the Oracle JRockit Mission Control Online Help.

  • You can see garbage collection pause times in the JRockit JVM by starting the JVM with -Xverbose:gcpause.

6.2 Tuning the Garbage Collector for Low Latencies

The first step for tuning the JRockit JVM for low latencies is to select a garbage collection mode that gives you short garbage collection pauses. The options available are:

For more information about garbage collector options, see Section 4.2, "Selecting and Tuning a Garbage Collector."

6.2.1 Dynamic Garbage Collection Mode Optimized for Deterministic Pause Times

Applications that require minimal latency, such as those used in the telecom and finance industries, cannot tolerate the unpredictable pause times caused by common garbage collection strategies. To avoid these long pause times, the JRockit JVM provides deterministic garbage collection, a dynamic garbage collection mode that keeps the garbage collection pauses short and deterministic.

Set the deterministic garbage collector as follows:

java -Xgc:deterministic -Xms:1g -Xmx:1g myApplication

The garbage collector try to keep the garbage collection pauses below the given pause target. How well it succeeds depends upon the application and the hardware. For example, a pause target of 30 milliseconds has been verified on an application with 1 GB heap and an average of 30 percent of the live data or less at collection time, running on the following hardware:

  • 2 x Intel Xeon 3.6 GHz, 2 MB level 2 cache, 4 GB RAM

  • 4 x Intel Xeon 2.0 GHz, 0.5 MB level 2 cache, 8 GB RAM

Running on slower hardware, with a different heap size and with more live data might break the deterministic behavior or cause performance degradation over time, while faster hardware or less live data might allow you to set a lower pause target.

The default pause target for the deterministic mode is 30 milliseconds, and can be changed with the -XpauseTarget:time option.

Example:

java -Xgc:deterministic -Xms:1g -Xmx:1g -XpauseTarget:40ms MyApplication

This command starts the JVM with the garbage collection optimized for short and deterministic pauses and a pause target of 40msec.

For more information, see the documentation on -XpauseTarget.

The deterministic garbage collector optimizes the compaction for the given pause target and does not use a nursery. Further tuning of compaction and nursery size should thus be unnecessary when the deterministic garbage collector is used.

6.2.2 Dynamic Garbage Collection Mode Optimized for Short Pauses

The dynamic garbage collection mode optimized for short pauses is useful for applications that don't require quite as short and deterministic pauses as the deterministic garbage collector guarantees. This garbage collection mode selects a garbage collection strategy to keep the garbage collection pauses below a given pause target (500 milliseconds by default). Compaction is also adjusted automatically to keep down the pause times caused by compaction.

Set the pausetime priority as follows:

java -Xgc:pausetime myApplication

If you use the pausetime priority but find that the default (500 milliseconds) is too long, you can specify a target pause time by using the -XpauseTarget option.

Example:

java -Xgc:pausetime -XpauseTarget=200ms myApplication

Note that there is a certain trade off between short pauses and application throughput. Shorter garbage collection pauses require more overhead in bookkeeping and can cause more fragmentation, which lowers the performance. If your application can tolerate pause times longer than 500 milliseconds you can increase the pause target to increase the application's performance.

The target value is used as a pause time goal and by the dynamic garbage collector to more precisely configure itself to keep pauses near the target value. Using this option enables you to specify the pause target to be between 200 milliseconds and 5 seconds. If you do not specify a pause target, the default remains 500 milliseconds.

The garbage collection mode for short pauses optimizes the compaction for the given pause target, so further tuning of the compaction should not be necessary. The nursery size is static for this garbage collection mode and has to be tuned manually.

6.2.3 Static Generational Concurrent Garbage Collection

If you want to use a static garbage collector and still experience minimal pause times, use a concurrent garbage collector. Generally, using a generational garbage collector is preferable to using a single-spaced garbage collector since a generational garbage collector gives you better application throughput.

To use a generational concurrent garbage collector, enter the following at the command line:

java -Xgc:gencon myApplication

To use a single-spaced concurrent garbage collector, enter the following at the command line:

java -Xgc:singlecon myApplication

When you use a static garbage collector, you might have to tune the nursery size and the compaction manually.

6.3 Tuning the Heap Size

You can resize the heap by using the -Xms (initial and minimum heap size) and -Xmx (maximum heap size) command-line options when you launch the JRockit JVM. Usually you can set the initial and the maximum heap size to the same value. Increasing the heap size reduces the frequency of garbage collections. A larger heap can also take slightly longer to garbage collect, but this effect is usually not considerable until the heap reaches sizes of several gigabytes.

The best approach to tuning the heap size is to benchmark the application with different heap sizes. Monitor the garbage collection pauses as described in Section 6.1, "Measuring Latencies" and determine the largest possible heap size for your application.

The only exception is the deterministic garbage collector. The deterministic garbage collector is verified to work best with a heap size of about 1 GB.

To set the heap size, use the -Xms and the -Xmx options.

Example:

java -Xms:1g -Xmx:1g myApplication

For more information, see Section 4.4, "Optimizing Memory Allocation Performance."

6.4 Manually Tuning the Nursery Size

If you are running -Xgc:pausetime or -Xgc:gencon, you might want to tune the nursery size manually.

The size of the nursery is static when you use -Xgc:pausetime, but setting it manually results in a more even behavior. For more information about the default nursery size, see the documentation for -Xns in Oracle JRockit Command-Line Reference. Note that when you use the dynamic garbage collector, the nursery might also be turned off completely when single-spaced garbage collection is used.

Note:

Tuning the nursery size manually is often beneficial for both the pause times and the application throughput.

The default nursery size for -Xgc:gencon is static, and it might not be optimal for all applications. You might benefit from manually setting a custom nursery size. The nursery should be as large as possible, but the nursery size must be decreased if the pause time created by a young collection (nursery garbage collection) is too long. Tune the nursery size by benchmarking your application with several different nursery sizes while monitoring the garbage collection pauses as described in Section 6.1, "Measuring Latencies."

To set the size of the nursery, use the -Xns option.

Example:

java -Xgc:pausetime -Xns:64m myApplication

6.5 Manually Tuning Compaction

If you are using a static garbage collector, tuning compaction manually can help improve latencies. Compaction is performed during a garbage collection pause, and thus the compaction time affects the garage collection pause times. By default, the static garbage collectors use a compaction scheme that aims at keeping the compaction times fairly even, but does not put an upper bound on the compaction time.

You can limit the compaction manually by setting a static compaction area size (-XXcompaction) or by limiting the number of references that can be updated due to compaction (-XXcompaction:maxReferences). These actions does not guarantee an upper bound on the compaction time, but reduce the risk for long compaction times.

Note that if you set the compaction ratio to low, the heap slowly becomes more and more fragmented until it is impossible to find free space that is big enough for object allocation. The heap becomes full of dark matter (basically severe fragmentation). When this happens, a compaction of the complete heap is done, which can result in a pause time of up to half a minute. Dark matter is reported for the heap in a Flight Recorder recording.

For more information about limiting compaction, see Section 4.3.2, "Adjusting Compaction."

6.6 Tune when to Trigger a Garbage Collection

The -XXgcTrigger option determines how much free memory should remain on the heap when a concurrent garbage collection starts. If the heap becomes full during the concurrent garbage collection, the Java application cannot allocate more memory until garbage collection frees some memory, which might cause the application to pause. While the trigger value tunes itself at run time to prevent the heap from becoming too full, this automatic tuning might take too long. Instead, you can use -XXgcTrigger option to set, from the start, a garbage collection trigger value more appropriate to your application.

If the heap becomes full during the concurrent mark phase, the sweep phase reverts to parallel sweep (unless -XXnoParSweep has been specified). If this happens frequently and the garbage collection trigger does not increase automatically to prevent this, use -XXgcTrigger to manually increase the garbage collection trigger.

Example:

java -XXgcTrigger myApp

The current value of the garbage collection trigger appears in the -Xverbose:memdbg output whenever the trigger changes.