- 55 -
o
See if the garbage collector executes more often than you expect.
o
Use the
Runtime.totalMemory
and
Runtime.freeMemory
methods to monitor gross memory usage.
•
Check whether your communication layer has built-in tracing features.
o
Check whether your communication layer supports the addition of customized layers.
•
Identify the number of incoming and outgoing transfers and the amounts of data transferred in distributed applications.
Chapter 3. Underlying JDK Improvements
Throughout the progressive versions of Java, improvements have been made at all levels of the runtime system: in the garbage collector, in the code, in the VM handling of objects and threads,
and in compiler optimizations. It is always worthwhile to check your own application benchmarks against each version and each vendors version of the Java system you try out. Any differences in
performance need to be identified and explained; if you can determine that a compiler from one version or vendor together with the runtime from another version or vendor speeds up your
application, you may have the option of choosing the best of both worlds. Standard Java benchmarks tend to be of limited use in deciding which VMs provide the best performance for your
application. You are always better off creating your own application benchmark suite for deciding which VM and compiler best suit your application.
The following sections identify some points to consider as you investigate different VMs, compilers, and JDK classes. If you control the target Java runtime environment, i.e., with servlet
and other server applications, more options are available to you, and we will look at these extra options too.
3.1 Garbage Collection
The effects of the garbage collector can be difficult to determine accurately. It is worth including some tests in your performance benchmark suite that are specifically arranged to identify these
effects. You can do this only in a general way, since the garbage collector is not under your control. The basic way to see what the garbage collector is up to is to run with the
-verbosegc
option. This prints out time and space values for objects reclaimed and space recycled. The printout includes
explicit synchronous calls to the garbage collector using
System.gc
as well as asynchronous executions of the garbage collector, as occurs in normal operation when free memory available to
the VM gets low. You can try to force the VM to execute only synchronous garbage collections by using the
-noasyncgc
option to the Java executable no longer available from JDK 1.2. This option does not actually stop the garbage-collector thread from executing: it still executes if the VM
runs out of free memory as opposed to just getting low on memory. Output from the garbage collector running with
-verbosegc
is detailed in Section 2.2
. The garbage collector usually works by freeing the memory that becomes available from objects
that are no longer referenced or, if this does not free sufficient space, by expanding the available memory space by asking the operating system for more memory up to a maximum specified to the
VM with the
-Xmx -mx
option. The garbage collectors space-reclamation algorithm tends to change with each version of the JDK.
- 56 - Sophisticated generational garbage collectors, which smooth out the impact of the garbage
collector, are now being used; HotSpot uses a state-of-the-art generational garbage collector. Analysis of object-oriented programs has shown that most objects are short-lived, fewer have
medium lifespans, and very few objects are long-lived. Generational garbage collectors move objects through multiple spaces, each time copying live objects from one space to the next and
reclaiming the space used by objects that are no longer alive. By concentrating on short-lived objects—the early spaces—and spending less time recycling space where older objects live, the
garbage collector frees the maximum amount of space for the lowest impact.
[1] [1]
One book giving more details on garbage collection is Inside the Java 2 Virtual Machine by Bill Venners McGraw-Hill. The garbage collection chapter is also available online at
http:www.artima.com .
Because the garbage collector is different in different VM versions, the output from the
- verbosegc
option is also likely to change across versions, making it difficult to compare the effects of the garbage collectors across versions not to mention between different vendors VMs. But you
should still attempt this comparison, as the effect of the garbage collector can make a difference to the application. Looking at garbage-collection output can tell you that parts of your application are
causing significantly more work for the garbage collector, suggesting you may want to alter the flow of objects in those parts of the application. Garbage collection is also affected by the number
of threads and whether objects are shared across threads. Expect to see improvements in threaded garbage collection over different VM versions.
A JDK bug seems to prevent the garbage collection of threads until the
Thread.stop
method has been called on the terminated thread this is true even though the
Thread.stop
method has been deprecated in Java 2. This affects performance because the resources used by the thread are not released until the thread is garbage-
collected. Ultimately, if you use many short-lived threads in your application, the system will run out of resources and will not supply any further threads. See Alan
Williamsons article in the Java Developers Journal, July 1999 and November 1999.
Garbage-collection times may be affected by the size of the VM memory. A larger memory implies there will be more objects in the heap space before the garbage collector needs to kick in. This in
turn means that the process of sweeping dead objects takes longer, as does the process of running through a larger object table. Different VMs have optimal performance at different sizes of the VM,
and the optimal size for any particular application-VM pairing must unfortunately be determined by trial and error.
3.2 Replacing JDK Classes