pal*_*now 23 .net clr garbage-collection
阅读这篇古老但经典的文档编写高性能托管应用程序 - 入门,我发现了以下声明
GC是自我调整的,可根据应用程序内存要求进行自我调整.在大多数情况下,以编程方式调用GC将阻碍调整.通过调用GC.Collect"帮助"GC很可能无法提高应用程序性能
我正在处理在给定时间点内消耗大量内存的应用程序.当我在使用该内存的代码中完成时,我正在调用GC.Collect.如果我不这样做,我会出现内存异常.这种行为是不一致的,但在30%的时间里,我得到了一个内存不足.添加GC.Collect后,我从来没有得到这个内存不足的异常.即使这个最佳实践文件提出反对建议,我的行动是否合理?
Joe*_*orn 29
GC中发生的部分原因是内存中的对象是世代的,因此早期的收集比其他对象更频繁.这有助于通过不尝试一直收集长寿命对象来节省性能.
考虑到这一点,当你打电话给GC.Collect()自己时会发生两件事.首先,你最终会花更多的时间做收藏.这是因为除了手册GC.Collect()之外,仍会发生正常的背景集合.第二个是你会更长时间地留在内存中,因为你强迫某些东西进入一个不需要去那里的更高阶代.换句话说,自己使用GC.Collect()几乎总是一个坏主意.
在一些情况下,垃圾收集器并不总是表现良好.其中之一是大对象堆.对于大于特定大小的对象(80,000字节,IIRC,但现在可能已经过时),这是一个特殊的生成.这一代人几乎从未被收集过,而且几乎从未被压缩过.这意味着随着时间的推移,你最终可能会在内存中出现许多不会被释放的漏洞.物理内存实际上并未使用,并且可用于其他进程,但它仍然占用进程中的地址空间,默认情况下,您的地址空间限制为2GB.
这是OutOfMemory异常的一个非常常见的来源 - 您实际上并没有使用那么多内存,但是您在大对象堆中的漏洞占用了所有这些地址空间.到目前为止,这种情况最常见的方式是重复附加到大字符串或文档.这可能不是你,因为在这种情况下,对GC.Collect()的任何调用都不会包含LOH,但在你的情况下它似乎有帮助.但是,这是我见过的绝大多数OutOfMemory异常的来源.
垃圾收集器并不总是表现良好的另一个地方是某些东西会导致对象保持根.一个例子是事件处理程序可以防止收集对象.解决这个问题的方法是确保+=订阅事件的每个操作都有相应的-=操作来取消订阅它.但同样,GC.Collect()不太可能在这里提供帮助 - 对象仍然在某个地方生根,因此无法收集.
希望这为您提供了一个调查途径,以解决导致需要首先使用GC.Collect()的潜在问题.但是,如果不是,那么拥有一个有效的程序比一个失败的程序更好.在任何地方我都使用GC.Collect(),我会确保代码有充分的文档记录,说明你需要它的原因(没有异常)以及可靠地重现它所需的确切步骤和数据,以便将来可能需要的程序员删除它可以确定何时安全.
大多数人会说让你的代码正常运行比快速运行更重要.因此,当你不打电话时,它无法在30%的时间内工作GC.Collect(),那就胜过所有其他问题.
当然,这会导致更深层次的问题:"为什么会出现OOM错误?是否存在应该修复的更深层次的问题,而不仅仅是调用GC.Collect().
但是你发现的建议谈论了性能.如果它使您的应用程序在30%的时间内失败,您是否关心性能?
| 归档时间: |
|
| 查看次数: |
2464 次 |
| 最近记录: |