大对象堆压缩,什么时候使用较好?

19

首先,什么大小被认为是大?有没有办法确定堆中对象的大小?

.Net 4.5.1附带了LargeObjectHeapCompactionMode

将LargeObjectHeapCompactionMode属性设置为GCLargeObjectHeapCompactionMode.CompactOnce后,下一次完全阻塞的垃圾回收(和LOH压缩)将在不确定的未来时间发生。您可以使用以下代码立即压缩LOH:

GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;
GC.Collect();      
根据我的了解,紧缩LOH是一件坏事!那么哪个更糟糕?紧缩LOH还是LOH碎片化?


除非你真的有问题,否则不要担心垃圾回收。手动调整垃圾回收几乎没有任何优势。 - PMF
@HansPassant 哈哈哈...就性能而言,对于不太挑剔的程序员来说,它真的那么糟糕吗? - Kamyar Nazeri
1
这不是好或坏的问题,而是一种权衡。如果你的应用程序因LOH碎片而导致OOM,有时压缩LOH并从你的应用程序中挤出额外的运行时间可能会更好。另一个选择(在.NET 4.5之前是唯一的选择)是在LOH变得过于碎片化时重新启动应用程序。你需要使用和不使用LOH压缩来分析你的应用程序以确定性能影响。(我想另一个选择是避免创建大对象,例如如果你处理大数组,你可以将它们分段,但是...呃)。 - nothingisnecessary
1个回答

17

分配内存大小大于等于85 KB的对象会被放到LOH中。压缩LOH并不会有什么问题——只是LOH碎片化并不是绝大多数应用程序需要担心的事情,所以对他们来说,这并不值得花费精力去压缩。

当你分配几个大对象并且它们都从同一个地址空间页面中获取时,如果让其中一些对象被回收,那么该页面中剩余的可用空间可能会因为太小而无法使用,或者甚至被"遗忘"。意味着分配器不会再考虑重新使用它。

最终可用的干净页面越来越少,因此分配器将开始变慢,因为它强制移动对象,甚至开始抛出OutOfMemory异常。压缩可以将这些对象移动到新页面中,回收该自由空间。

你的应用程序是否具有这种对象使用模式?大多数应用程序都没有。在64位平台上,您甚至可能观察不到这一点,因为存在更多的地址空间可供碎片化,除非这已经成为了一个巨大的问题。


4
好的回答。我曾在ASP.NET Web应用程序中经常看到OutOfMemoryException错误,这是由于LOH碎片化导致的,因为这些应用不会经常(甚至从未)进行回收(经过WinDbg验证)。当然,在32位应用程序中,这种情况会更早地发生。例如,具有大型/复杂表单(并且使用ViewState)的ASP.NET应用程序通常会生成超过85 KB的ViewState字符串。过去,我的解决方案是设置一个回收计划,并以这样的方式编写应用程序,使得回收应用程序池对用户不可见(例如,不会以使他们失去工作的方式终止会话)。最后,有了LOH压缩功能! - nothingisnecessary

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接