什么导致.NET中的内存碎片

Mat*_*att 48 .net c# memory-leaks memory-management fragmentation

我正在使用Red Gates ANTS内存分析器来调试内存泄漏.它一直警告我:

内存碎片可能导致.NET保留过多的可用内存.

要么

内存碎片正在影响可以分配的最大对象的大小

因为我有强迫症,所以必须解决这个问题.

有哪些标准编码实践有助于避免内存碎片.你能通过一些.NET方法对其进行碎片整理吗?它会帮助吗?

Dan*_*ker 10

GC堆以不同方式处理大对象分配.它不会压缩它们,而只是组合相邻的空闲块(就像传统的非托管内存存储区).

更多信息:http://msdn.microsoft.com/en-us/magazine/cc534993.aspx

因此,使用非常大的对象的最佳策略是分配它们一次然后保持它们并重用它们.

  • 出于好奇,我想知道为什么LOH对象大小没有四舍五入到4096的下一个倍数?看起来这有助于在某些操作系统上下文中进行压缩(只需移动虚拟页面指针而不是复制内存),并且还可以大大减少碎片.由于LOH对象通常最小为85K,因此从四舍五入到4K块的开销将是5%或更少. (2认同)

Joh*_*ren 9

你知道,我有点怀疑这里的内存分析器..NET中的内存管理系统实际上是通过在内存中移动来尝试对堆进行碎片整理(这就是为什么需要固定内存以便与外部DLL共享).

在较长时间内进行的大量内存分配容易产生更多碎片.虽然小的短暂(短)内存请求不太可能导致.NET碎片化.

这也是值得思考的事情.使用.NET的当前GC,及时分配的内存通常在空间中间隔很近.这与碎片相反.即您应该按照打算访问它的方式分配内存.

它只是托管代码还是包含P/Invoke,非托管内存(Marshal.AllocHGlobal)或GCHandle.Alloc(obj,GCHandleType.Pinned)等内容?

  • GC不压缩大对象堆,即对象> 85KB的对象.一旦LOH碎片化,就无法对其进行碎片整理. (6认同)

And*_*tes 7

.NET Framework 4.5.1能够在垃圾回收期间显式压缩大对象堆(LOH).

GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;
GC.Collect();
Run Code Online (Sandbox Code Playgroud)

请在GCSettings.LargeObjectHeapCompactionMode中查看更多信息