LAB-1205: Java Application Performance Analysis
Exercise 1: Young generation too small
Learning goals of this exercise
In this exercise you will learn:
- Basics of HotSpot memory areas
- How to use the javaperf GUI to launch the Java 2D Demo application and monitor its performance with Visual GC.
- Understand where to find the command line tuning for each exercise
- How to recognize when the young generation is too small
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:
- Young Generation (includes eden and the two survivor spaces)
Objects are initially created in eden. Because many objects are
short-lived they may die (get collected) in the young generation.
One survivor space
is empty at any time, and serves as a destination of the next,
copying collection of any live objects in eden and the other survivor
space. Objects are copied between survivor spaces in this way until
they are old enough to be tenured, or promoted to the old generation
- Old Generation (sometimes called the Tenured generation)
If objects have a long enough lifetime, or if there are more live
objects than fit in the young generation, then they get promoted to the
old generation.
- Permanent Generation
This is a special area which contains class and method objects for the application itself.
- Stack
As Java is a multi-threaded environment, each thread consumes some
memory on the stack. For large server processes handling
thousands of threads it is important to consider the total impact of
thread stacks on memory footprint.
- Native
Of course the Java Virtual Machine is implemented natively on each
platform on which it runs. A certain amount of native memory is consumed
by the JVM itself. Generally speaking developers do not need to
worry about this small amount of memory.
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
- 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.
- In Exercise 0 you should have started
the javaperf GUI which looks like this:

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

- 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.
- You will see the Java 2D Demo application start.... Immediately click on the "Transforms" tab:

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

- You should then see a window like this:

- 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:
- Watch the sawtooth pattern emerge in the Old Generation graph in the "Graph" pane of Visual GC
- 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:

- 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.
- 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"):

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.
- You can view the jstat log that was collected during the exercise
by expanding the "Log files" JTree node and clicking on jstat.log:

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
- You will notice at the top of each exercise page there is a navigation bar with the following buttons:
| First Exercise
|
|
Previous Exercise
|
|
|