calling System.gc to suggest garbage collection

R

Roedy Green

The general advice we tend to give is don't use System.gc. Just let
the system do its thing. Further, calling it does not FORCE garbage
collection, just suggests it may be a good time for it.

Are there any exceptions to this general rule?

e.g. when you know the system will likely be idle for a while.

when you know the number of live objects is at a minimum just now.
 
M

markspace

Roedy said:
The general advice we tend to give is don't use System.gc. Just let
the system do its thing. Further, calling it does not FORCE garbage
collection, just suggests it may be a good time for it.

Are there any exceptions to this general rule?

e.g. when you know the system will likely be idle for a while.

when you know the number of live objects is at a minimum just now.


I would say: after careful user testing. Not just profiling but
actually observing how users really interact with the system. Then
consider some judicious use of System.gc() *if* you can justify results.

Do some A-B testing with versions of the system with System.gc() and
without. If there isn't a clear increase in users' satisfaction it's
not worth it.

Also: use other GCs (specify them on the command line or in the Jar
manifest) and change around the parameters for each GC too, first,
before modifying the code. System.gc() is a last resort only.

Note: I've never gone through these steps myself. Idle speculation only.
 
D

Daniel Pitts

Roedy said:
The general advice we tend to give is don't use System.gc. Just let
the system do its thing. Further, calling it does not FORCE garbage
collection, just suggests it may be a good time for it.

Are there any exceptions to this general rule?

e.g. when you know the system will likely be idle for a while.

when you know the number of live objects is at a minimum just now.
I like the we IntelliJ handles this. There is a button that the user can
press if they feel like calling gc. the "widget" in question also
displays memory stats (current heap allocation and size). Its just too
bad that Java doesn't have any mechanism to report the progress of the
current garbage collection cycle.

Actually, the more I deal with Windows, the more I think GC time is
taken up by a lot of "thrashing", because Windows swaps out the less
frequently used memory, and Java "explores" that memory to determine
whether to collect it or not.

I wonder if there could be some sort of algorithm that is
virtual-memory-swap aware.
 
L

Lew

Peter said:
To the extent that a smaller working set reduces paging, anything Java
can do to reduce the amount of memory it actually accesses would be
productive. But that is already a basic goal, even ignoring
page-swapping issues. GC is more costly the more objects that need to
be inspected, even if all those objects are already swapped-in.

And in fact, the Java GC implementation has features intended to address
that goal of reducing memory accesses (e.g. object generations).

Young-generation collections don't touch dead objects.

<http://www.ibm.com/developerworks/library/j-jtp01274.html>
"copying collectors do not visit dead objects, a heap with a large number of
temporary objects, which is a common situation in Java applications, costs
very little to collect; simply trace and copy the live objects to a survivor
space and reclaim the entire heap in one fell swoop."

The same article discusses why one should *not* call 'System.gc()':
"... developers often mistakenly think they are helping the garbage collector
is the use of System.gc() ... Unfortunately, System.gc() triggers a full
collection, which includes tracing all live objects in the heap and sweeping
and compacting the old generation. This can be a lot of work."

<http://www.javaworld.com/javaworld/jw-01-2002/jw-0111-hotspotgc.html>
"The HotSpot JVM uses a two-machine-word object header, rather than the
three-word header found in most other JVMs. This saves as much as 10 percent
of the heap size for typical applications while accelerating the code to scan
all objects.

"The HotSpot JVM also eliminates the concept of handles. This reduces memory
usage and speeds processing. In the HotSpot JVM, object references are
implemented as direct pointers, providing C-speed access to instance variables."
Inasmuch as Java already does what it can to reduce the number of
objects it has to inspect during a GC pass, it thus also is already
doing what it can to reduce the active working set, reducing page swapping.

In what writers call "typical" usage patterns, it is claimed that 90-98% of
objects are dead before they get promoted to the tenured generation. That
means the young-generation collector only needs to visit 2-10% of the objects
in the nursery to do a collection.
Whether that qualifies in your mind as "virtual-memory-swap aware", I'm
not sure. But I think it's safe to say that the Sun developers who are
responsible for the JVM and its memory management implementation fully
expect Java to be running on systems with virtual memory management and
a swap file, and do take that into account to the extent that they can.

To respond to Roedy's question, everything I've read about the 'System.gc()'
call suggests that it's unwise to use. OTOH, I've heard anecdotes in the
field that suggest that it is useful, though none of those anecdotes seem to
come with descriptions of alternatives rejected, such as tuning the JVM's GC
parameters [1]. Some of those anecdotes related to situations where memory
was inappropriately retained ("packratted") and 'gc()' was a band-aid approach
that missed the real problem.

Simple logic suggests to me that hard-coded 'gc()' calls cannot "know" when
memory is tight, but the JVM always will. That means that 'gc()' will never
do better than regular GC at creating free memory when it's needed. As to
making it faster, if memory is not tight then triggering a 'gc()' is
unnecessary and therefore not "faster" in any useful sense. If memory is
tight, the JVM will trigger a GC anyway, so asking for it does not help. If
'gc()' doesn't help when memory is not tight, nor when memory is tight, then
there's never a need to call it.

If you think that 'gc()' might help, run the program in question twice under
load for a long time with the 'gc()' calls in place, once without the option
"-XX:-DisableExplicitGC" and once with. Measure the difference.

[1]
<http://java.sun.com/docs/hotspot/gc5.0/gc_tuning_5.html>
<http://java.sun.com/javase/technologies/hotspot/gc/gc_tuning_6.html>
 
L

Lew

Peter said:
So? It's not the dead objects that are the problem.

So? As you yourself said,
So, as importantly, a collection that only collects the nursery need not
touch all the other longer-lived objects that are tenured.

So, calling GC forces a full collection, so the tenured generation gets hit,
so you lose the benefit of the young-generation collection, so one should not
so force a collection, for that and other reasons so stated by you.

It's relevant because people thinking of calling 'gc()' may believe that the
total number of objects allocated is relevant, and should be aware that it's
generally only the number of live objects that affect GC time.

As for another point you made,
an application may ... have a large number of objects
in the tenured generation(s).

This is an important point. Many of the things people naively do to "help"
GC, such as reuse of a single object throughout a loop instead of reallocation
in each iteration, force promotion of objects to the tenured generation and
actually hurt memory management. They also tend to promote the scope of
references outside the block where they're used, a bad practice. It is
usually better to limit the lifetime of objects so they get dropped during
minor collections, keeping the size of the tenured generation as small as
practicable. This tends to help limit reference scope also.

Another benefit to keeping lifetimes short is that it helps prevent references
from tenured-generation objects into the young generation, another situation
that unnecessarily tenures objects.
 
A

Arne Vajhøj

Roedy said:
The general advice we tend to give is don't use System.gc. Just let
the system do its thing. Further, calling it does not FORCE garbage
collection, just suggests it may be a good time for it.

Are there any exceptions to this general rule?

e.g. when you know the system will likely be idle for a while.

when you know the number of live objects is at a minimum just now.

It will never make a not working program work.

Unless you happen to be a GC expert, then it could just as well
make performance worse as improve performance.

The only good reason to put it in the code is if you are paid
by line - in which case adding an extra line gets you extra money.

Arne
 
K

Kevin McMurtrie

Roedy Green said:
The general advice we tend to give is don't use System.gc. Just let
the system do its thing. Further, calling it does not FORCE garbage
collection, just suggests it may be a good time for it.

Are there any exceptions to this general rule?

e.g. when you know the system will likely be idle for a while.

when you know the number of live objects is at a minimum just now.

There are some bugs in Java 1.5 that can be helped with a periodic
forced GC:

- File descriptor leaks in NIO
- CMS auto-tuning into oblivion
- CMS lockups due to heap complexity

I haven't seen them yet in 1.6. Of course, calling System.gc() is a
workaround with severe impacts on performance. By default it invokes
the slowest type of GC available. It's better to solve the original
problem.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,770
Messages
2,569,584
Members
45,075
Latest member
MakersCBDBloodSupport

Latest Threads

Top