[Gc] Re: GC needs to be invoked manually
hans.boehm at hp.com
Wed Aug 31 13:15:08 PDT 2005
> -----Original Message-----
> From: Martin Wartens
> Sent: Wednesday, August 31, 2005 4:38 AM
> To: gc at napali.hpl.hp.com
> Subject: [Gc] Re: GC needs to be invoked manually
> > Traceable_allocator and GC_MALLOC_UNCOLLECTABLE allocate
> memory that
> > is traced for pointers by the collector (i.e. such objects
> are viewed
> > as always reachable, and anything they point to is also
> > reachable.) Hence I think the behavior you saw earlier is the
> > expected behavior.
> No, why? I don't understand that.
Looking at your earlier example again, I think I may have
It looks to me like you set up elements n2 which pointed to an STL
map, which point to n1. (The source as posted didn't work for me,
due to bad line wrapping of // comments, and missing includes.
I fixed it. Apologies if I got this wrong.)
The STL map uses traceable_allocator. Hence pieces of its data
will be uncollectable. Those pieces point to n1, which will be
uncollectable. I agree that n2 should be collectable.
The reason the n2 pieces end up not getting collected is that the large
majority of the allocated memory is uncollectable and inside STL maps.
As a result, the collector decides it's not worthwhile to trigger
a collection, because the heap occupancy will be high even after
it finishes. Hence collections don't happen.
The heuristics used by the collector are always debatable. But in
this case I think it's actually dead on.
However, in the case you describe below, it turns out that they do
have serious problems. Basically the same thing is happening here;
most of the heap appears to be uncollectable, and hence collections
appear futile. However, if it did collect, finalizers would run, the
destructors would get executed, and a bunch of memory would be
The collector actually tries to increase GC frequency once it notices
that finalization results in a lot of explicit deallocation. But
it never triggers a GC, and hence never notices.
It turns out this is already fixed in gc7.0alpha5, which uses a
more robust heuristic.
In general, this code is well outside the comfort zone for tracing
collectors. You really don't want a very large fraction of the
objects to be finalizable (e.g. by inheriting from gc_cleanup),
or reachable from finalizable objects. Making all the objects
collectable works MUCH better.
> > I don't see the behavior you describe below. But I do see
> that many
> > objects do not have their destructor called. If I insert
> the GC_FREE
> > call, nearly all objects do have their destructors called. This is
> > also expected,
> > but for more complicated reasons:
> Ok, I forget to comment in the GC_FREE. Just imagine the
> program with the
> GC_FREE commented in. To be sure that I didn't post something
> stupid, I tried this program on a linux machine. The compile line was:
> g++ -g -I./include -o mygctest mygctest.cpp ./lib/libgc.a
> ./lib/libgccpp.a -
> lpthread -ldl
> I saw the same behaviour as reported before, but it turned
> out that the last
> working array size on this machine was 56, not 26 as on the
> windows machine.
> Please retry with a large number for the array size, and look if the
> destructors still get called.
> > - It may be that in your environment no collections take
> place between
> > the program starts and the time it exits. Set the GC_PRINT_STATS
> > environment variable to verify.
> I did that. The output is given below. There is only one
> collection indicated.
> Thanks for looking at my problem.
> Best regards,
> Increasing heap size by 65536 after 0 allocated bytes
> Initiating full world-stop collection 1 after 0 allocd bytes
> --> Marking for collection 1 after 0 allocd bytes + 0 wasted bytes
> Collection 0 finished ---> heapsize = 65536 bytes
> World-stopped marking took 0 msecs
> Complete collection took 0 msecs
> Grew fo table to 1 entries
> Grew fo table to 2 entries
> Grew fo table to 4 entries
> Grew fo table to 8 entries
> Grew fo table to 16 entries
> Grew fo table to 32 entries
> Grew fo table to 64 entries
> Grew fo table to 128 entries
> Increasing heap size by 65536 after 37624 allocated bytes
> Grew fo table to 256 entries
> Increasing heap size by 65536 after 93448 allocated bytes
> Grew fo table to 512 entries
> Increasing heap size by 69632 after 166756 allocated bytes
> Grew fo table to 1024 entries
> Increasing heap size by 90112 after 230656 allocated bytes
> Increasing heap size by 122880 after 319360 allocated bytes
> Grew fo table to 2048 entries Increasing heap size by 163840
> after 436476 allocated bytes Increasing heap size by 217088
> after 598044 allocated bytes Grew fo table to 4096 entries
> Increasing heap size by 290816 after 811960 allocated bytes
> Increasing heap size by 385024 after 1099192 allocated bytes
> Increasing heap size by 548864 after 1476088 allocated bytes
> Grew fo table to 8192 entries Increasing heap size by 696320
> after 2023636 allocated bytes Increasing heap size by 929792
> after 2712756 allocated bytes Grew fo table to 16384 entries
> Increasing heap size by 1241088 after 3635824 allocated bytes
> Increasing heap size by 1654784 after 4865808 allocated bytes
> Grew fo table to 32768 entries Increasing heap size by
> 2203648 after 6504908 allocated bytes Elements created: 20000
> Elements destroyed: 0
> Gc mailing list
> Gc at linux.hpl.hp.com
More information about the Gc