To GC.Collect or not?

[亡魂溺海] 提交于 2019-11-30 00:07:00

Part of what goes on in the GC is that objects in memory are generational, such that early generations are collected more frequently than others. This helps save performance by not trying to collect long-lived objects all the time.

With that in mind, two things can happen when you call GC.Collect() yourself. The first is that you end up spending more time doing collections. This is because the normal background collections will still happen in addition to your manual GC.Collect(). The second is that you'll hang on to the memory longer, because you forced some things into a higher order generation that didn't need to go there. In other words, using GC.Collect() yourself is almost always a bad idea.

There are a few cases where the garbage collector doesn't always perform well. One of these is the large object heap. This is a special generation for objects larger than a certain size (80,000 bytes, IIRC, but that could be old now). This generation is hardly ever collected and almost never compacted. That means that over time you can end up with many sizable holes in memory that will not be released. The physical memory is not actually used and is available for other processes, but it does still consume address space within your process, of which you are limited to 2GB by default.

This is a very common source for OutOfMemory exceptions — you're not actually using that much memory, but you have all this address space taken up by holes in the large object heap. By far the most common way this happens is repeatedly appending to large strings or documents. This probably is not you, because in this scenario no amount of calls to GC.Collect() will companct the LOH, but in your case it does seem to help. However, this is the source for the vast majority of the OutOfMemory exceptions I've seen.

Another place where the garbage collector does not always perform well is when certain things cause objects to remain rooted. One example is that event handlers can prevent an object from being collected. A way around this is make sure that every += operation to subscribe an event has a corresponding -= operation to unsubscribe it. But again, a GC.Collect() is unlikely to help here - the object is still rooted somewhere, and so can't be collected.

Hopefully this gives you an avenue of investigation to solve your underlying problem that causes the need to use GC.Collect() in the first place. But if not it is, of course, better to have a working program than a failing program. Anywhere I do use GC.Collect(), I would make sure the code is well documented with the reason why you need it (you get exceptions without) and the exact steps and data required to reproduce it reliably so that future programmers who may want to remove this can know for sure when it is safe to do so.

Most people would say that making your code work correctly is more important than making it fast. Thus, it it fails to work 30% of the time when you don't call GC.Collect(), then that trumps all other concerns.

Of course, that leads to the deeper question of "why do you get OOM errors? Is there a deeper issue that should be fixed, instead of just calling GC.Collect().

But the advice you found talks about performance. Do you care about performance if it makes your app fail 30% of the time?

Generally speaking, GC.Collect shouldn't be necessary. If your images exist in unmanaged memory, then be sure to use GC.AddMemoryPressure and GC.RemoveMemoryPressure appropriately.

From your description it sounds like Disposeable objects are not being disposed, or you're not setting member values that will be replaced to null before the operation. As an example of the latter:

  • Get table, display in grid
  • (User hits refresh)
  • Form is disabled while data is refreshed
  • Query comes back, new data is populated in the grid

You can clear out the grid in the interim since it's about to be replaced anyway; you will temporarily have both tables in memory (unnecessarily) while it is replaced if you don't.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!