11

Possible Duplicate:
When is it acceptable to call GC.Collect?

From what I know the CLR does all this garbage collection for you, but is there a reason to manually call GC.Collect()?

Is it for cases when you close a file, dispose of an image resource or an unmanaged resource, that you should call GC.Collect() to quickly clean up the unused memory immediately?

Community
  • 1
  • 1
Joan Venge
  • 315,713
  • 212
  • 479
  • 689
  • 4
    http://stackoverflow.com/questions/478167/when-is-it-acceptable-to-call-gc-collect, http://stackoverflow.com/questions/1149197/gc-collect, http://stackoverflow.com/questions/5248838/to-gc-collect-or-not, etc..... – Cocowalla Mar 21 '11 at 20:52

5 Answers5

7

Is it for cases when you close a file, dispose of an image resource or an unmanaged resource, that you should call GC.Collect() to quickly clean up the unused memory immediately?

No, not really. This is typically handled via IDisposable.

There are very few reasons to call GC.Dispose() directly, and doing so often causes a lot of harm, since it interferes with the internal heuristics of the GC in .NET. There are, however, rare occurrences when it's useful.

For example, if you have a operation that is a rare operation which uses a large object graph, and you know that your going to be "idle" afterwards, you might want to call GC.Collect immediately afterwards to release the memory used by the objects. That being said, this is often still best left up to the system to handle.

For the most part, I've found the most useful scenario for GC.Collect() is for debugging. It can help you guarantee that you don't have a leak, since it allows you to force a full Gen2 collection.

Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
  • Also this was another thing I was wondering. Will the memory be immediately GC'ed when the Dispose method is called? – Joan Venge Mar 21 '11 at 20:54
  • 1
    @Joan: Dispose is really unrelated to (managed) memory. It frees (immediately) the **natively allocated** memory associated with the image, as well as it's OS Handle, but not any managed memory. – Reed Copsey Mar 21 '11 at 20:56
7

http://blogs.msdn.com/b/ricom/archive/2003/12/02/40780.aspx

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

Right from the equine's oral orifice.

dotalchemy
  • 2,459
  • 19
  • 24
4

I usually use GC.Collect() to bring the heap to a mostly-known state. For example, when benchmarking, you need to make sure that you start each run from a known state, and GC.Collect() helps with this.

It should not be used to dispose of unmanaged resources -- for that you should use using or manually call Dispose.

Gabe
  • 84,912
  • 12
  • 139
  • 238
  • Thanks, can you please tell me what you mean by "mostly-known state"? – Joan Venge Mar 21 '11 at 20:55
  • 1
    I mean that the heap is compacted and does not contain unreferenced objects. In other words, each benchmark run should be interrupted by garbage collection for approximately the same amount of time. – Gabe Mar 21 '11 at 20:57
3

I can just think of two cases where GC.Collect() might be useful:

  • In unit tests. Call GC.Collect() before and after some test to find potential memory leaks. In this case consider using GC.WaitForPendingFinalizers(), because finalizers are executed in a separate thread. This means that classes with finalizers do not immediately release all ressources after calling GC.Collect().

  • In long living processes like Windows Services where there is a long idle time. Call GC.Collect() before it goes idle. Reason: If a process is idle, the garbage collector will not kick in, thus unused memory will be not released during idle time.

GC.Collect() should not be called for the purpose of "quickly clean up the unused memory immediately". Having a forced release of memory does not pay off the overall performance caused by an active garbage collection.

Theo Lenndorff
  • 4,556
  • 3
  • 28
  • 43
1

The only time I've ever used it in code that wasn't specifically to compare memory usage of two or more different approaches to something had the following scenario:

In a web application (and hence, long-running), there were a few very large collections that would generally be re-built at most a few times a day, often much less frequently.

Several objects within that collection would be equivalent, and hence a lot of memory could be saved by replacing references to one such object to a reference to the other (after building the collection was read-only in use, and hence the aliasing involved was safe). So first the collection would be built, but then it would be reduced in size, killing many objects.

This meant that there was a sudden spike in the number of objects destroyed per second, that would then not happen again for several hours at least. As such the GC would not correctly judge the amount of collection needed, and that memory was about to be needed to build the second large collection. Hence doing a manual collection every thousand of clean-up operations did have a positive effect on performance (enough to sometimes go from the application crashing on the third collection, to it being dependable).

A lot of measurement was done to make sure it was indeed beneficial in this case.

The two factors that made this beneficial were:

  1. A lot of object deaths happened.
  2. The event causing this was rare in the lifetime of the application.

Without both of those being true, the manual call would be needless. Without a lot of object deaths, there's no point, and if it wasn't rare in the application's lifetime, the GC would have self-tuned to cope.

Jon Hanna
  • 110,372
  • 10
  • 146
  • 251