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 normally not under your control. (Sun does intend to introduce an API that will allow a pluggable garbage collector to replace the one delivered with the VM, but building your own garbage collector is not a realistic tuning option. Using a pluggable third-party garbage collector doesn't give you control over the garbage collector either.) 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). The -noasyncgc 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, 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 collector's space-reclamation algorithm tends to change with each version of the JDK.

Sophisticated generational garbage collectors, which smooth out the impact of garbage collection, 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 objectsthe early spacesand 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 that you may want to alter the flow of objects in those parts. 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.

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, and the optimal size for any particular application-VM pairing must be determined by trial and error.