开发者

When to use GC.Collect() in .NET? [duplicate]

This question already has answers here: 开发者_如何学C Closed 11 years ago.

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?


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.


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.


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.


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.


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜