views:

3565

answers:

10

The general advise is that you should not call GC.Collect from your code, but what are the exceptions to this rule?

I can only think of a few very specific cases where it may make sense to force a garbage collection.

One example that springs to mind is a service, that wakes up at intervals, performs some task, and then sleeps for a long time. In this case, it may be a good idea to force a collect to prevent the soon-to-be-idle process from holding on to more memory than needed.

Are there any other cases where it is acceptable to call GC.Collect?

+4  A: 

Have a look at this article by Rico Mariani. He gives two rules when to call GC.Collect (rule 1 is: "Don't"):

When to call GC.Collect()

M4N
Been there already. I'm not trying to find excuses for doing something that you shouldn't do, but I would like to know if there are any specific cases where it would be acceptable.
Brian Rasmussen
+4  A: 

One case is when you are trying to unit test code that uses WeakReference.

Brian
+2  A: 

In your example, I think that calling GC.Collect isn't the issue, but rather there is a design issue.

If you are going to wake up at intervals, (set times) then your program should be crafted for a single execution (perform the task once) and then terminate. Then, you set the program up as a scheduled task to run at the scheduled intervals.

This way, you don't have to concern yourself with calling GC.Collect, (which you should rarely if ever, have to do).

That being said, Rico Mariani has a great blog post on this subject, which can be found here:

http://blogs.msdn.com/ricom/archive/2004/11/29/271829.aspx

casperOne
I agree that would be a good solution as well.
Brian Rasmussen
+17  A: 

If you have good reason to believe that a significant set of objects - particularly those you suspect to be in generations 1 and 2 - are now eligible for garbage collection, and that now would be an appropriate time to collect in terms of the small performance hit.

A good example of this is if you've just closed a large form. You know that all the UI controls can now be garbage collected, and a very short pause as the form is closed probably won't be noticeable to the user.

Jon Skeet
+1  A: 

Scott Holden's blog entry on when to (and when not to) call GC.Collect is specific to the CF, but the rules generally apply to all managed development.

ctacke
+3  A: 

The short answer is: never!

BankZ
+12  A: 

I use GC.Collect only when writing crude performance/profiler test rigs; i.e. I have two (or more) blocks of code to test - something like:

GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
TestA(); // may allocate lots of transient objects
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
TestB(); // may allocate lots of transient objects
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
...

So that TestA() and TestB() run with as similar state as possible - i.e. TestB() doesn't yet hammered just because TestA left it very close to the tipping point.

A classic example would be a simple console exe (a Main method sort-enough to be posted here for example), that shows the difference between looped string concatenation and StringBuilder.

If I need something precise, then this would be two completely independent tests - but often this is enough if we just want to minimize (or normalize) the GC during the tests to get a rough feel for the behaviour.

During production code? I have yet to use it ;-p

Marc Gravell
And I probably add "WaitForPendingFinalizers" (or whatever it is) too in this case ;-p
Marc Gravell
A: 

This isn't that relevant to the question, but for XSLT transforms in .NET (XSLCompiledTranform) then you might have no choice. Another candidate is the MSHTML control.

Chris S
+3  A: 

You can call GC.Collect() when you know something about the nature of the app that the garbage collector doesn't. Since the GC amounts to a pretty well-written expert system, that means pretty much never.

The best example I can think of where you might have some extra information is a app that cycles between idle periods and very busy periods. You want the best performance possible for the very busy periods and therefore want to use the idle time to do some clean up.

However, most of the time the GC is smart enough to do this anyway.

Joel Coehoorn
+4  A: 

The best practise is to not force a garbage collection in most cases. (Every system I have worked on that had forced garbage collections, had underlining problems that if solved would have removed the need to forced the garbage collection, and speeded the system up greatly.)

There are a few cases when you know more about memory usage then the garbage collector does. This is unlikely to be true in a multi user application, or a service that is responding to more then one request at a time.

However in some batch type processing you do know more then the GC. E.g. consider an application that.

  • Is given a list of file names on the command line
  • Processes a single file then write the result out to a results file.
  • While processing the file, creates a lot of interlinked objects that can not be collected until the processing of the file have complete (e.g. a parse tree)
  • Does not keep match state between the files it has processed.

You may be able to make a case (after careful) testing that you should force a full garbage collection after you have process each file.

Another cases is a service that wakes up every few minutes to process some items, and does not keep any state while it’s asleep. Then forcing a full collection just before going to sleep may be worthwhile.

The only time I would consider forcing a collection is when I know that a lot of object had been created recently and very few objects are currently referenced.

I would rather have a garbage collection API when I could give it hints about this type of thing without having to force a GC my self.

See also "Rico Mariani's Performance Tidbits"

Ian Ringrose