Long latencies might manifest, for example, as single transactions that time out in a transaction-based application while the overall performance is good. The problem usually is uneven performance and nondeterministic latencies.
This chapter includes the following topics:
Long latencies might indicate that the application is not tuned for short and deterministic pause times. Before engaging in time-consuming troubleshooting and mitigation tasks, try tuning the JVM to optimize for short pause times. For information about tuning the JVM for short pause times, see the Oracle JRockit Performance Tuning Guide.
Note that there are trade-offs exist between low latencies and high overall application throughput.
High latencies that cause transactions to time out are often caused by pauses for garbage collection. To reduce the individual garbage-collection pause times the garbage collector runs in a mostly concurrent mode; that is, the garbage collection is, mostly, performed while the Java threads are still running. This causes some additional work for the garbage collector, which has to keep track of changes during the concurrent phases of the garbage collection. The garbage collections are also less efficient because objects that are allocated during the concurrent garbage collection, are not garbage collected until the next garbage collection cycle. This can force the JVM to collect garbage more frequently.
If you have disabled or limited compaction by using the -XXcompaction
command-line option, to reduce the pause times caused by compaction, the heap might become fragmented. (You can analyze fragmentation by using the Flight Recorder tool.)
You can increase the overall throughput while keeping the latencies low by allowing longer garbage collection pauses or by manually tuning the garbage collection. For more information, see the Oracle JRockit Performance Tuning Guide.
This section provides information to troubleshoot latency issues related mostly to concurrent garbage collection; for example, -Xgc:deterministic
and -Xgc:pausetime
.
The garbage collection trigger (gctrigger
) value is the amount of free heap space that should be available when a concurrent garbage collection starts, to allow the Java threads to continue allocating objects during the entire garbage collection. The gctrigger
value changes at run time, to avoid situations where the heap becomes full during concurrent garbage collection.
Monitor the gctrigger
value by using the output of the -Xverbose:memdbg
option or by using the Flight Recorder tool.
A continuously increasing gctrigger
value indicates that the load on the application is too high for the concurrent garbage collector. Decrease the load on the application.
A continuously increasing gctrigger
value could also indicate that the Java heap size is too small; the behavior might improve if you increase the heap size.
Monitor the garbage collection reasons for the old collections by using either the -Xverbose:memdbg
option or the Flight Recorder tool. The normal garbage collection reason for a mostly concurrent old collection is heap too full.
If the old collections are triggered frequently due to failed object allocation, the gctrigger
is too low. Increase the gctrigger
by using the -XXgcTrigger
option or decrease the load on the application.
Monitor the pause times for young collections by using the output of the -Xverbose:gcpause
option or through Flight Recorder recordings.
If the young-collection pause times are too long, decrease the nursery size by using the -Xns
option; alternatively, run a single-generational garbage collector.
Monitor the garbage-collection pause times in a Flight Recorder recording. Check the pause parts for pause times that are too long. If the pause parts for Compaction
are too long, decrease the pause target. If the pause parts in Mark:Final
, especially the ones concerning RefrenceQueues
, are too long, the problem might be due to numerous java.lang.ref.Reference
objects in the application. Redesign the Java application using fewer reference objects. You could also try decreasing the heap size; this causes reference objects to be handled more frequently, but reduces the number of reference objects to handle at each old collection.
If the solutions provided in this section do not help you solve the performance degradation problem, contact Oracle Support, as described in Chapter 9, "Contacting Oracle for Support."