This is the mail archive of the java@gcc.gnu.org mailing list for the Java project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Shrinking the GC root set


As noted earlier[*] programs compiled with gcj tend to have
large static root sets and consequently reduced GC efficiency for
medium/large Java applications.  On x86 the combined size of data/bss in
libgcj alone is nearly 1.5MB; this is currently scanned on each
collection.

Hans mentioned using GC_exclude_static_roots() to ignore large static data
areas.  The difficulty with this is in identifying enough
large pointer-free static data areas to be worthwhile.

As an experiment I've built libgcj with a bare minimum root set.  The
strategy is:

1) Use GC_clear_roots() and GC_no_dls to prevent scanning all static data
segments by default.

2) Add known roots from native code in libgcj (the GC handles it own
internal roots).

3) During each collection, push all initialized classes onto the mark
stack with a procedure descriptor.

It turns out there are only a few roots in libgcj apart from Java classes
and static reference variables:  the JNI global/local ref tables, the lock
table for hash synchronization, and a few exceptions allocated in
prims.cc.  Other roots I was able to ignore by allocating storage with 
_Jv_Malloc instead of _Jv_AllocBytes, e.g. for the string intern table.
(I need to be cautious of these so as not to introduce memory leaks, of
course.)

I'll send my changes to java-patches in case anyone is interested.  There
are a few pitfalls of my patch:

- Native code that relies on having static variables scanned by default
will fail.

- Performance is sometimes worse than without.  I attribute this to the
overhead of _Jv_MarkObj vs. a simple length descriptor.  (The length
descriptor fails for compiled classes because it omits e.g. the
field/method tables.)

- The table of initialized classes is hardcoded to 1024 entries.  (This
ought to be easy to fix.)

- Thread-local allocation fails with a SIGSEGV in GC_local_malloc(), so
I've built libgcj with thread-local allocation disabled.  (I'm unsure if
this problem was introduced by clearing roots.)

Comments?

Jeff

[*] - http://gcc.gnu.org/ml/java/2002-06/msg00073.html


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]