Sun Microsystems Logo
First Previous Next Last Overview
 

LAB-1205: Java Application Performance Analysis

Exercise 1: Young generation too small

Learning goals of this exercise

In this exercise you will learn:

Background for this exercise

All the exercises have the same format: the javaperf GUI is used to launch the Java 2D Demo program with command line tuning specific to each exercise.  (NOTE: the Java 2D Demo program is included with the J2SDK).  As described in detail below you will start the Java 2D Demo program, then click in the Transforms tab and then into the Shear area.  The Shear demonstration is great for experimenting with JVM tuning because it creates a great deal of temporary objects.

Then you can actually watch the various areas of memory in the running Java process with the Visual GC tool.  Visual GC gives an excellent overview of what's happening inside a JVM.  When you combine this visualization with additional statistics gathered during the test you can make some judgements about the performance of the target application.

After running for about one minute, stop the Java 2D demo by clicking the Stop button in the javaperf GUI.  VisualGC will also be stopped for you.  Upon exiting VisualGC a summary of GC statistics will be visible in the javaperf GUI.

There is really no substitute for fully reading the Tuning Garbage Collection with the 5.0 Java™ Virtual Machine document to really understand the subtleties of how garbage collection works.  Nevertheless here is a very high level definition of HotSpot memory areas:

Managing the sizes of the Java heap are important for performance.  Often implementations of the JVM use different garbage collection algorithms for the young generation and for the old generation.  A "minor GC" is a garbage collection of the young generation.  A "full GC" (sometimes called major GC) is a garbage collection of the Old generation.  Understanding the basics of tuning the Java heap can lead to dramatic increases in performance.

Steps to follow

  1. The first time you run this exercise several things happen very quickly.  It is a good idea to skim all of these steps before starting to get an idea of what happens during the exercise.

  2. In Exercise 0 you should have started the javaperf GUI which looks like this:

    javaperf GUI launcher


  3. You can start the first exercise by clicking on "01: Young Generation Too Small" and then clicking the "Start" button:

    javaperf GUI launcher


  4. The javaperf GUI launcher will now start the Java 2D application, determine it's virtual machine identifier (vmid), and then use that vmid to run the jstat program to gather basic GC statistics (which are displayed in the javaperf GUI) and also launch the Visual GC application. For the first exercise it may take a minute or so for all of these applications to start. Subsequent exercises will start much faster.

  5. You will see the Java 2D Demo application start....  Immediately click on the "Transforms" tab:

    Java 2D Demo startup window

  6. Then click on the sliding Duke in the "Shear" area so it fills the entire window:

    Java 2D Transforms

  7. You should then see a window like this:

    Java 2D Shear

  8. A few seconds later the Visual GC application will be started to monitor the Java 2D Demo application. 
    • Visual GC
      Shows basic application information like the elapsed time of the process and a number of static "counters" (e.g. the command line options).
      Note that the screen areas representing the Perm gen, Old gen, Eden and the survivor spaces (S0 and S1) are sized proportionately to the maximum capacities of the spaces.
    • Graph
      Shows statistics as they evolve over time.  For all of the exercises the sampling interval has been chosen to be one second.
    • Survivor Space Histogram
      The Histogram panel displays a snapshot of the age distribution of objects in the active survivor space after the last Young generation collection. The display is comprised of 32 identically sized regions, one for each possible object age. Each region represents 100% of the active Survivor Space and is filled with a colored area that indicates the percentage of the survivor space occupied by objects of the given age.
    This is what the three Visual GC panes look like:

    Visual GC pane
    Graph pane
    Survivor Age Histogram pane


  9. Watch the sawtooth pattern emerge in the Old Generation graph in the "Graph" pane of Visual GC

  10. After a minute or so of run time (as shown at the top of the "Visual GC" pane or in the javaperf GUI) then
    quit the Java 2D Demo application by clicking the "Stop" button in the javaperf GUI. This will stop the Java 2D demo, the Visual GC program (and the jstat statistics program). You will see a summary of GC statistics that were collected by jstat in the javaperf GUI:

    Exercise 01 Stop


  11. So for this example run we have had 306 minor collections (this is the young generation), 9 full collections (this is the old generation) and we have a spent a total of 1.8% of the total runtime in GC.

  12. To see how the command line arguments were set, click on the "Settings" tab (or expand the "Exercise 01" JTree node on the left and click on "Settings"):

    Exercise 01 settings

    Note that the arguments are separated into categories for "compiler", "heap", "gc" and "other" for convenience, but they are all simply combined on the command line prior to starting the Java 2D demo application.

  13. You can view the jstat log that was collected during the exercise by expanding the "Log files" JTree node and clicking on jstat.log:

    Exercise 01 logs

Summary

Now you have an understanding of the HotSpot memory areas and you've actually seen them by running Visual GC.

How do you know the young gen is too small?  The first clue is the sawtooth pattern in the old gen. (NOTE: the rate at which objects are generated depends on the specific hardware you are using... In some cases it may take more than a minute to see the sawtooth pattern appear.)   This is happening because there are objects that are still alive that are getting promoted to the old gen (and/or because there are many objects which are too big to be allocated in the young gen).  Another clue is the large number of minor GC's for such a short run time.

Why is a small young gen a problem?  Old gen collections are generally more expensive than minor collections.  By finding the appropriate size of the young gen to match the application's rate of generating temporary objects then the faster minor GC will manage these objects while letting only longer lived objects to get promoted to the old gen.

In all of these exercises the initial and maximum young generation size is set the same (to avoid dynamic resizing).
In a similar way the overall initial and maximum heap size is set the same.  So for the most part we will only change the size of the young gen and old gen.

You might wonder, why did we set -XX:MaxTenuringThreshold=0 ?  We are basically saying that any object that is alive during a minor GC should get immediately promoted to the old gen.  When running on certain platforms without this parameter we don't get the familar sawtooth pattern (unless you manually resize the Shear area to be very large).

Next Steps