Sunday, December 9, 2012

JRockit JVM performance tuning

JRockit having two different versions:


1.JRockit Real time
2. JRockit Mission control

The major difference is JRockit mission control is license free where as JRockit RT is a license basesd.

Difference between Sun Jdk vs JRockit JDK:


Sun JDK :
In this mechanism, the byte code is read and the translated into machine language,but these results are not saved in the memory. So every time even if the same method is run again and again, the JVM has to translate the code into machine language. This means machine code will not be reusable as it is not saved anywhere in the memory.

JRockit JDK:

In this mechanism, once a method is run, the byte code is translated to machine language and this is saved in the memory. This means if the method is run again, there is no need for translation and the machine code is reused.

Because of the interpreter mechanism used by sun jdk, the start up time for the server is faster because it does not have to save the machine code in memory. Once the translation is done for a method, it moves to the other one. Where as oracle JRockit saves the code, which is why  start up takes longer. For the same reason, oracle JRockit uses more memory than sun jdk.

In the long run, JRockit gives a slightly better performance as compared to sun jdk.



The Oracle JRockit JDK provides the necessary tools to monitor your application at run time. When tuned correctly according to the recommendations in this document, the JVM runs smoothly and provides timely results. If run-time monitoring indicates problems, use the recommendations in this document to better tune the JVM.




Performance Tuning:

Step1) Tuning the JRockit JVM results in trade-offs among short garbage collection pause times, high application throughput, and low memory footprint.

  1. Pause Times and Throughput
  2. Performance and Memory Footprint

Concurrent and Stop-the-World

The trade-off between garbage collection pauses and application throughput is partially caused by the mostly concurrent garbage collection strategy that enables short garbage collection pauses. No matter how efficient the garbage collection algorithm is that stops the Java threads during the entire garbage collection, a garbage collection algorithm that allows the Java threads to continue to run during parts of the garbage collection has shorter individual garbage collection pauses. A concurrent algorithm requires more work, because new objects are created and references between objects change during the garbage collection. All these changes must be kept track of, which causes overhead, and the garbage collector must make all the changes, which adds extra work. The more the garbage collector can do while the Java threads are paused, the less processing it has to do.

Compaction Pauses and Throughput

The mark and sweep garbage collection model can cause heap fragmentation when chunks of memory too small for allocated objects are freed between blocks of live objects. Compacting the heap reduces this fragmentation. Fragmentation has a negative impact on the overall throughput because it makes object allocation more difficult and garbage collections more frequent. The JRockit JVM does partial compaction of the heap in each garbage collection; this compaction occurs while all Java threads are paused. Moving objects takes time and compaction takes more time the more objects it moves. Reducing the amount of compaction shortens the compaction pause times, but it can reduce the overall throughput by allowing more fragmentation.

Performance and Memory Footprint

A small memory footprint is desirable for applications that run on machines with limited memory resources. There is a trade-off for having a small memory footprint and both application throughput and garbage collection pauses. The following sections describe some of the reasons for this trade-off.



Heap Size and Throughput

A large heap reduces the garbage collection frequency and fragmentation, improving the throughput of the application; however, a large heap increases the memory footprint of the Java process.


Bookkeeping and Pause Times

When you use a garbage collection mode that optimizes for short pauses, the Oracle JRockit JVM uses more advanced bookkeeping to track changes in the heap, references to compacted objects, and so on. All these increase the memory footprint. To tune the memory usage for bookkeeping, you must select a different garbage collection mode or strategy.





Tuning the Heap Size

The heap is where the Java objects are located. While a large heap requires fewer garbage collections, it can take longer to complete these collections. Typically, a heap should be at least twice the size of the live objects in the heap, meaning that at least half of the heap should be freed at each garbage collection. For server applications, you can usually set the heap as large as the available memory in your system allows, as long as this does not cause paging.
Use the following command-line options to set the heap size:
  • -Xms:size: To set the initial and minimum heap size
  • -Xmx:size: To set the maximum heap size
Example:
java -Xms:800m -Xmx:1000m MyServerApp
This command starts the JVM with a heap of 800 MB and allows the heap to grow up to 1000 MB.


Setting the Heap Size

Command-line options: -Xms:size -Xmx:size
The heap size affects allocation speed, garbage collection frequency and garbage collection times. A small heap fills quickly and must be garbage collected more often. A large heap results in overhead at garbage collection times. A heap that is larger than the available physical memory in the system must be paged out to disk, which leads to long access times or even application freezes, especially during garbage collection.
In general, the additional overhead caused by a larger heap is smaller than the gains in garbage collection frequency and allocation speed, as long as the heap does not get paged to disk. A good heap size setting is a heap that is as large as possible within the available physical memory.
There are two parameters for setting the heap size:
  • -Xms:size sets the initial and minimum heap size.
  • -Xmx:size sets the maximum heap size.
Example:
java -Xms:1g -Xmx:1g MyApplication
This command starts the JVM with a heap size fixed to 1 GB.
If the optimal heap size for the application is known, Oracle recommends that you set -Xms and -Xmx to the same value. This gives you a controlled environment where you get an appropriate heap size right from the start.





Setting the Heap Size on 64-bit Systems

On 64-bit systems a memory address is 64 bits long, which makes it possible to address much more memory than with a 32-bit address. Each reference also requires twice as much memory. To reduce the memory usage on 64-bit systems, the JRockit JVM can use compressed references. Compressed references reduce the references to 32 bits, and can be used if the entire heap can be addressed with 32 bits. Compressed references are enabled by default whenever applicable.
You can modify compressed references for various address bits and heap sizes by using the -XXcompressedrefs command-line option. For more information about -XXcompressedrefs and its parameters





Tuning the Garbage Collection

Garbage collection reclaims space from objects that are no longer in use so that new objects can be allocated to this space. During garbage collection, system resources are used. By tuning the garbage collection, you can decide how and when the resources are used. The JRockit JVM has three garbage collection modes and a number of static garbage collection strategies. These enable you to tune the garbage collection to suit requirements of your application.
Select the garbage collection mode by using one of the following command-line options:
  • -Xgc:throughput optimizes garbage collection for application throughput.
  • -Xgc:pausetime optimizes garbage collection for short garbage collection pauses.
  • -Xgc:deterministic optimizes garbage collection for very short and predetermined garbage collection pauses.
    The -Xgc:deterministic option is available only as part of Oracle JRockit Real Time 
You might start a transaction-based application that requires low latencies with the following command:
java -Xgc:pauseTime MyTransactionApp
This command starts the JVM with garbage collection optimized for short garbage collection pauses.




Selecting and Tuning a Garbage Collector

The effect of garbage collection can be distributed in different ways depending on the choice of the garbage collection method. Use the command-line option -Xgc:mode to specify a garbage collection mode.

Selecting a Garbage Collection Mode

The garbage collection modes adjust the memory management system at run time, optimizing for a specific goal depending on the mode used.
The following are the garbage collection modes:
  • throughput: Optimizes the garbage collector for maximum application throughput.
  • pausetime: Optimizes the garbage collector for short and even pause times.
  • deterministic: Optimizes the garbage collector for very short and deterministic pause times.
The garbage collection modes use advanced heuristics to tune the following parameters at run time:
  • Nursery size
  • Compaction amount and type

    Throughput Mode

    Command-line option: -Xgc:throughput
    The throughput mode can either use a generational garbage collector (if -Xgc:genpar or only -Xgc:throughput is specified) or a nongenerational garbage collector (if -Xgc:singlepar or -Xgc:parallel is specified).
    The throughput mode uses as little CPU resources as possible for garbage collection, giving the Java application as many CPU cycles as possible. The JRockit JVM achieves this by using a parallel garbage collector that stops the Java application during the entire garbage collection duration and uses all CPUs available to perform the garbage collection. Each individual garbage collection pause might be long, but in total, the garbage collector takes as little CPU time as possible.
    Use the throughput mode for applications that demand a high throughput but are not very sensitive to the occasional long garbage collection pause.
    The throughput mode is the default when the JVM runs in the -server mode (which is default) or can be enabled by using the -Xgc:throughput option.
    Example:
    java -Xgc:throughput MyApplication
    
    This command starts the JVM with the garbage collection mode optimized for throughput.



    JVM Diagnostics :

    Eliminate Optimization Problems
    At times, optimization could be the cause of the slow JVM startup, especially on single-CPU machines.


    Eliminate Application Problems
    If you determine that the slow start is due to problems in the Java application, investigate the cause of the problem from the application viewpoint. The problem is probably caused by methods that are subject to unnecessary synchronization or an insufficient number of synchronized resources. Try to locate the methods that are causing the bottleneck and, if possible, modify the code of your Java application.
    Note that you can use the Flight Recorder tool to analyze synchronization problems.




    Possible Causes for Slow JVM Startup

    An application might seem slow when it starts because,
    • The application might be waiting to import files.
    • A large number of methods might have to be compiled.
    • There might be a problem in code optimization (especially on single-CPU machines).
    • The problem might be caused by the Java application and not the JVM.
    • You recently migrated from a third-party development JVM to the JRockit JVM as the production JVM.
      The JRockit JVM is a just-in-time (JIT) compiling JVM designed for long-running applications. It compiles methods into machine code when the methods are called for the first time. So the application is relatively slow at startup because numerous new methods are compiled. However, after the application starts, it runs fast. Moreover, as the application runs, the JVM optimizes frequently called methods, improving the performance further.



     Diagnosing Slow Application Startup

    The startup could be slow when, for example, the application is searching for a data file, looking up data in a database, and so on.
    If you suspect that the application is causing the slow startup, use the Flight Recorder tool to record and analyze the application data.


    Diagnosing Slow JVM Startup

    • Check whether the JVM compiles numerous methods at startup, by using the -Xverbose:codegen option. When you use this option, the following information about the methods being compiled is displayed:
      • Name of the method
      • Memory location
      • Duration of the compilation process
      • The total amount of time spent in compiling code since the application started.
      The following is an example of the output of the -Xverbose:codegen option.
      [INFO ][codegen][00004] #23 (Normal) java/lang/Object.registerNatives()V
      [INFO ][codegen][00004] #23 0.113-0.114 0x0000000100011B60-0x0000000100011C6B
         0.80 ms 128KB 0 bc/s (11.60 ms 63252 bc/s)
      [INFO ][codegen][00004] #24 (Normal)
         java/lang/OutOfMemoryError.<init>(Ljava/lang/String;)V
      [INFO ][codegen][00004] #24 0.115-0.115 0x0000000100011C80-0x0000000100011C92 0.38
         ms 64KB 15662 bc/s (11.99 ms 61731 bc/s
      
      Note that after the JIT compilation is complete, the application runs faster than during startup, because when the methods are called subsequently, the JVM runs the precompiled code.
    • Check the time taken to optimize methods by using the -Xverbose:opt option.









Please let me know if you face any problems.