heap fragmentation?

Jeff Sturm jsturm@one-point.com
Wed Jun 5 11:44:00 GMT 2002


Thanks. Following your questions and some more experimentation I
understand the issues better. What I'm seeing isn't significant
fragmentation, rather that the GC is too eager to expand the heap.
On Tue, 4 Jun 2002, Boehm, Hans wrote:
> The only thing I see here that's clearly suboptimal is the size of
> static roots. That basically gets added to the size of live heap data
> when making heap expansion decisions, since it needs to be scanned for
> each collection.

OK, that makes sense. I hadn't made the connection
that min_words_allocd() governs collection frequency, affecting heap
growth as well.
> We should really be trying to reduce that. If a lot
> of it comes from CNI code, you might try calling
> GC_exclude_static_roots() on pointer-free static data.

More than 90% of that 6MB comes from Java code, of which very little
actually points to the heap. We've talked about reducing that before. I
wish uninitialized classes in particular weren't scanned at all.
> Remaining questions: Why did the heap grow to 32 MB? If you have the
> complete log, you might ssearch for the heap expansions. Or you can put
> a breakpoint in GC_expand_hp_inner().

It expanded on allocation. As I understand GC_allocobj(), it tries
several ways to populate the free list (assuming incremental mode):
1) If free list is non-empty, return.
2) If a collection is in progress, continue.
3) Else initiate a collection if enough bytes have been allocated.
4) Try to sweep blocks.
5) If free list is still empty, try to allocate a new heap block.
6) If free list is still empty, try to expand the heap.
7) Repeat.
> With a heap size of 20MB, it
> should insist on allocating something like (20+6)/3 = ~9MB between
> collections. With 5 MB in use, that should be fairly easy.

I picked a bad snapshot to send you. At the point of expansion, much
more than 5 MB had been in use. Subsequently, full collections reduced
that to typical levels.
Note that this figure is really (20+6)/6 = ~5MB in incremental mode.
I'm a little concerned about the policy of automatically expanding the
heap to manage allocation failure before the GC thinks it is ready for
another collection. A great deal of objects allocated are extremely
short-lived so a collection is always productive, e.g. if 5 MB have been
allocated since the last collection I can usually count on getting at
least 4 MB back. For my purposes I would rather spend the cycles to
reclaim those (if possible) than expand. I realize that some minimum
free space should be maintained to prevent thrashing.
To that end I need fast collections, which is why I'm looking at
incremental/generational mode. A problem is that fetching dirty bits
and scanning root sets currently requires a great deal of the 50ms limit.
> It would be interesting to know whether the heap was fragmented at the
> point of heap expansion. The snapshot we're looking at here doesn't
> look bad to me.

You mean GC_words_wasted? Actually very few. It was a bad example. The
free list was probably also nearly empty at that time, based on further
measurements.
> I assume the collection here was triggered explicitly? Otherwise it
> shouldn't have been triggered after 25K of allocation.

Yes.
> I don't think gcj ever configures the collector so that the heap can
> shrink. Defining USE_MUNMAP should work on some platforms.

On Solaris GET_MEM uses calloc() because mmap() confuses the collector
into blacklisting too much. We figured that out last year. Perhaps 
it could free() unused blocks, not that it would do much good.
> It's not clear to me that SMALL_CONFIG will help here.

My hunch was that smaller blocks would lead to less fragmentation. Right
or wrong, that probably doesn't matter here.
> Incremental collection generally hurts the memory footprint.

Well that's just confusing to me... surely smaller, more frequent
collections ought to help? If not, why is Sun's VM so space efficient
(besides compacting of course).
In case anyone is wondering, I'm evaluating how many VM's I can
practically support per host. Something like 64 MB of unexpected heap
growth is no real problem for a single VM, but multiply by 20...
Jeff


More information about the Java mailing list

AltStyle によって変換されたページ (->オリジナル) /