views:

114

answers:

6

If you stick to managed code and standard coding (nothing that does unconventional things withe CLR) in .NET, is there any reason to manually invoke the GC or request to run finalizers on unreferenced objects?

The reason I ask is thaty I have an app that grows huge in Working Memory set. I'm wondering if calling

System.GC.Collect();

and

System.GC.RunFinalizers();

would help, and if it would force anything that wouldn't be done by the CLR normally anyways.

+7  A: 

No, it won't help. Don't do it. The CLR already handles all the memory management-related stuff in a fine way, and no explicit call will do something it's not already doing.

Try to look for memory leaks in your program: while .NET languages are memory-managed, it doesn't mean it always knows when you're not using a certain object anymore. For instance, objects attached as event listeners to other objects are considered rooted by the GC and won't be collected.

You can try SOS to seek leaks.

If there is really no leak, then your program truly needs the memory it has.

zneak
In ideal world Your answer is true, but when You are creating many objects and they loose their range pretty fast You will suck memory pretty fast. Is it memory leak? I wouldn't say so, GC is just not fast enough :) Of course You can re-think and optimize such solution, loosing readability in most cases, or call System.GC.Collect() every some reasonable amount of loops - then your code is clean, GC does perfectly its job and nobody gets hurt.
Rafal Ziolkowski
@Rafal Ziolkowski: I don't see how it's a problem. The host can ask the GC to run if it needs memory back.
zneak
+1  A: 

Yes, it's useful for writing unit tests that require certain Dispose/Finalize methods to be called deterministically (as seen from the view of your test) for example.

Henrik
+1  A: 

Of course there's a reason, they wouldn't have provided the Collect() method otherwise. They are few and far between though. Only ever use it when you know that a whole bunch of long-lived objects that would have been promoted to gen #2 are ready to be collected. Or to release a COM object that has lots of references that you cannot possibly track should really be unloaded. Or to work around crummy code that doesn't call Dispose() when it should.

It's rare.

Hans Passant
A: 

Leave it to CLR. Use some tools to identify the issue that you have mentioned.

KZoal
+3  A: 

@zneak : Actually, this isn't entirely true. I ran into a situation in which I was intermittently and non-deterministically running out of memory while running through a large set of data (that involved a lot of creating and destroying managed objects) in c#.

Manually invoking garbage collection once per loop fixed it. However, this is rare, and in most cases leaving the garbage collector to itself is the best course, however, I wouldn't make a blanket statement that one should never manually invoke GC as that is simply incorrect.

Donnie
I'll take your word, but I really don't know how this could happen. The garbage collector is supposed to run before an OutOfMemoryException is thrown.
zneak
I thought so too, but, apparently not. Once I made the leap that GC was the only non-deterministic thing in my code and put in the `GC.Collect; GC.WaitForPendingFinalizers;` pair the problems went away. Used to crash with an OOM exception once every few days, hasn't crashed in over 3 months now. Bug in the GC? Maybe, dunno.
Donnie
That does sound like a CLR bug. The guys at Microsoft usually quickly respond to bug reports, you should give it a try. (Also, if you answer a comment, you should put @person (like @zneak) at the beginning of it; that way, _person_ gets notified of the answer.)
zneak
A: 

Also, System.GC.Collect(); is useful when you want to measure memory consumption by some containers. For example, you have Database store and service which cached indexed pieces of data, which a loaded sequentially and synchronously. When your service is under memory pressure it can unload large pieces of least recently used data.

Andrew_B