.NET Forum / .NET Framework / New Users / April 2005
GC, Should I care?
|
|
Thread rating:  |
Chris Mayers - 15 Apr 2005 13:47 GMT I am trying to track a suspected memory leak in an application I'm writing and through repeated simplification of my project, I have found the following which is quite easily replicated should you be prepared to give me 5 minutes of your time...
Create a new C# (Probably the same in VB dotNET but I've not tried it) Windows application with 2 forms, the default form -Form1 and one other one. that has a bunch of controls on it (say 20 buttons, 20 labels and a DataGrid) - Form2.
On the default form, add a button to display the second form with some code like:
private void button1_Click(object sender, System.EventArgs e) { using (form2 formTwo = new form2()) { form2.ShowDialog(); } }
also on Form1 add a label, and a timer that updates the label text as follows (updates every 5 seconds -Interval = 5000-):
private void timer1_Tick(object sender, System.EventArgs e) { label1.Text = GC.GetTotalMemory(False); }
and finally a button that forces a Garbage Collection:
private button2_Click(object sender, System.EventArgs e) { GC.Collect(); }
OK, my question/query is this, if I repeatedly click the button to open the second form, then close the second form, click the button, close the form etc. about 20-30 times, the display of GetTotalMemory seems to keep going up, and even after forcing Garbage Collections, never seems to get fully reclaimed. Should I care? and if I should, what (if anything) can I do about it?
I would really appreciate an answer from someone who understands these things...
Thanks a lot,
Chris.
Jsp - 15 Apr 2005 14:38 GMT Use "SetProcessWorkingSetSize(-1,-1)" from kernel32.dll instead.
> I am trying to track a suspected memory leak in an application I'm writing > and through repeated simplification of my project, I have found the [quoted text clipped - 50 lines] > > Chris. Sean Hederman - 17 Apr 2005 09:51 GMT > Use "SetProcessWorkingSetSize(-1,-1)" from kernel32.dll instead. This does not clear up memory leaks. All it does is tell Windows to tidy up the processes working set. This may result in less memory use for the moment, but will significantly slow down your app when it needs to expand it's working set (e.g. when it creates a new variable).
>> I am trying to track a suspected memory leak in an application I'm >> writing [quoted text clipped - 51 lines] >> >> Chris. Phil Wilson - 15 Apr 2005 15:29 GMT If Form2 has a collection of controls on it, they've got Finalizers and Dispose methods that aren't being called (because the only Dispose you're calling is on Form2 itself). So it's possible that you have a queue of Finalizers (for those controls) that haven't been called yet, and that queue grows every time you instantiate a form2. The CLR Profiler should help you see what's going on. http://www.microsoft.com/downloads/details.aspx?FamilyId=86CE6052-D7F4-4AEB-9B7A -94635BEEBDDA&displaylang=en
 Signature Phil Wilson [Microsoft MVP-Windows Installer]
> I am trying to track a suspected memory leak in an application I'm writing > and through repeated simplification of my project, I have found the [quoted text clipped - 50 lines] > > Chris. Chris Mayers - 15 Apr 2005 15:54 GMT OK,
So should I override the Dispose method in Form2 and use it to call Dispose on each of its controls, I was thinking of giving that a shot anyway.
Chris.
> If Form2 has a collection of controls on it, they've got Finalizers and > Dispose methods that aren't being called (because the only Dispose you're > calling is on Form2 itself). So it's possible that you have a queue of > Finalizers (for those controls) that haven't been called yet, and that queue > grows every time you instantiate a form2. The CLR Profiler should help you > see what's going on. http://www.microsoft.com/downloads/details.aspx?FamilyId=86CE6052-D7F4-4AEB-9B7A -94635BEEBDDA&displaylang=en
> > I am trying to track a suspected memory leak in an application I'm writing > > and through repeated simplification of my project, I have found the [quoted text clipped - 50 lines] > > > > Chris. Stefan Simek - 15 Apr 2005 16:12 GMT > OK, > > So should I override the Dispose method in Form2 and use it to call Dispose > on each of its controls, I was thinking of giving that a shot anyway. > > Chris. No, Control.Dispose disposes all child controls as well. Because every form derives from Control, in disposes all it's children recursively.
HTH, Stefan
>>If Form2 has a collection of controls on it, they've got Finalizers and >>Dispose methods that aren't being called (because the only Dispose you're >>calling is on Form2 itself). So it's possible that you have a queue of >>Finalizers (for those controls) that haven't been called yet, and that The above is *not* true.
> queue > [quoted text clipped - 69 lines] >>> >>>Chris. AMercer - 15 Apr 2005 16:31 GMT Re "So should I override ..", the answer is no, unless you are chasing a real memory leak. if you want to see memory reclaimed, then use GC.WaitForPendingFinalizers in cunjunction with GC.Collect. Once upon a time, while chasing a memory leak, I coded
Dim i As Integer Dim l As Long For i = 1 To 3 GC.Collect() GC.WaitForPendingFinalizers() l = GC.GetTotalMemory(True) Next
My purpose was to coerce garbage collections so I could watch the memory leak grow without the confusion of delayed garbage collections. When growth stopped, I had fixed my memory leak. FYI the leak was my failure to explicitly call Dispose for a context menu that I created in a non-standard way.
The bottom line is that you don't need to worry about GC absent a problem like a memory leak. The code fragment above may help you discover if you do have a memory leak. Ditto Jsp's comment re trimming the working set. Both are useful in development and debugging, but they have no place in production code.
> OK, > [quoted text clipped - 71 lines] > > > > > > Chris. Jesse Towner - 17 Apr 2005 07:35 GMT > Re "So should I override ..", the answer is no, unless you are chasing a real > memory leak. if you want to see memory reclaimed, then use [quoted text clipped - 8 lines] > l = GC.GetTotalMemory(True) > Next Yes, the correct way to force a garbage collection and ensure everything that can be collected does indeed get collected is as follows:
Int64 totalMemory;
GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect();
totalMemory = GC.GetTotalMemory(); The reason you must make two calls to GC.Collect is because the first call queues inaccessible objects with finalizers in the finalization queue--in other words, they're automatically promoted to the second generation. This is why you always hear that you should avoid the use of finalizers, and to make sure to explicitly and deterministically dispose of such objects. Anyway, you then wait for the all of the objects to be finalized, and then you perform a full collection again to collect the now finalized objects.
Your loop implicitly does this; however, I'd make sure to retrieve the total memory available after an additional call to GC.Collect, instead of calling it immediately after GC.WaitForPendingFinalizers.
- Jesse Towner
AMercer - 17 Apr 2005 11:10 GMT We are saying and doing the same thing. By coding GC.GetTotalMemory(True), I am doing the 2nd GC.Collect() that you indicate. The for loop is used to counter the following (related) info found in the remarks section of the documentation for GC.GetTotalMemory(forceFullCollection):
"If forceFullCollection is true, this method waits a short interval before returning while the system collects garbage and finalizes objects. The duration of the interval is an internally specified limit determined by the number of garbage collection cycles completed and the change in the amount of memory recovered between cycles. The garbage collector does not guarantee that all inaccessible memory is collected."
My objective was an accurate estimate managed memory to help chase a memory leak. The phrases "short interval" and "does not guarantee" did not inspire confidence, hence the for loop. In my environment, 3 iterations were productive, and 4 or more were not.
> > Re "So should I override ..", the answer is no, unless you are chasing a real > > memory leak. if you want to see memory reclaimed, then use [quoted text clipped - 34 lines] > > - Jesse Towner
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|