[Gtk-sharp-list] Disposing problem

Bruno Fernandez-Ruiz brunofr@olympum.com
Sun, 09 Nov 2003 20:57:35 +0200


I understand from your message that under Gtk# managed objects are
prevented to be GC'ed, and queued to be dereferenced in the unmanaged
code. Your code should work as it allows idle cycles to happen
(yielding). I will try it out on my Gtk# application and let you know if
it works.

Now, I still have a question beyond Gtk#, and more related to the Mono
runtime. 

Please accept my apologies if I am getting it wrong, but I assimilate
the mono VM to a JVM, where both GUI and non GUI managed applications
run on a managed memory heap. Roughly speaking, on a JVM, if after a
marking cycle from the GC thread, there is not enough marked objects to
be reclaimed to leave enough free memory for a requested allocation, the
actual heap is expanded up. If the max heap is reached, and there is
still more memory requested, then the application crashes with an out of
memory error. 

In my sample using mono, I would expect the VM GC mark policy, whichever
policy is used, to limit the amount of memory used, as the test objects
are not kept referenced, at least by the application code. So either,
the GC mark and sweep is not happening, or something else is keeping a
reference to the objects that prevents finalization. Instead, CPU sky
rockets, and the system starts swapping memory until freeze.

Could somebody please give me some light? My experience from heavily
loaded server-side applications, enterprise level, ist that optimized GC
is critical for system performance.

Thanks!
Bruno

public class Test
{
        ~Test ()
        {
                Console.WriteLine ("Finalized");
        }
                                                                                                                                                                                   
        public static void Main ()
        {
                for (long i = 10000000000; i > 0; i--)
                        new Test ();
        }
}


On Sun, 2003-11-09 at 18:32, Jonathan Pryor wrote:
> The problem is that you're not a GUI app. :-)
> 
> PerformQueuedUnrefs is called from the Idle handler for the GUI.  The
> Idle handler is run whenever the GUI is not busy.
> 
> (Recall that GUIs are event-driven, so if the user isn't doing anything,
> and the app isn't doing anything, then the app is idle, so you can do
> background work during idle processing.)
> 
> Your sample app doesn't have a GUI, so there's never an "idle time", so
> the idle handler is never run, so PerfrmQueuedUnrefs is never called.
> 
> Some possible solutions:
>   - Insert the code:
> 	while(GLib.MainContext.Iteration()) {
> 		// do nothing
> 	}
>     This should explicitly run the idle handler.  This should be run
>     after the .Dispose() call.
> 
>   - Make Object.Dispose virtual, then make Pixbuf.Dispose free memory 
>     immediately.
> 
>     This probably isn't a good idea, as GTK+ requires that all objects
>     be disposed from the same thread, which is what PerformQueuedUnrefs
>     does (since the idle handler is only run on the GUI thread, so only
>     one thread will ever do the unrefs).
> 
>     Pixbuf might not have this requirement, though.  I have no idea.
> 
> The first option is the safest and simplest option, if it works.  Please
> try it and let us know.
> 
>  - Jon
> 
> On Sat, 2003-11-08 at 13:55, Bruno Fernandez-Ruiz wrote:
> > On Sat, 2003-11-08 at 20:54, Gonçal Carrero Puig wrote:
> > > Anyone knows why idle is never calling PerformedQueuedUnrefs?
> > 
> > I have seen similar problems in due to the GC thread never entering, and
> > the heap expanding until memory exhaustion. Try to create many dummy
> > objects that implement IDisposable, and see if they get reclaimed. When
> > running the attached sample, I freeze the system and run out of memory.
> > No collection ever happens. 
> > 
> > Is GC disabled by default in mono?
> > 
> > Bruno
-- 
Bruno Fernandez-Ruiz <brunofr@olympum.com>
The Olympum Group,  http://www.olympum.com