我正在使用Red Gates ANTS内存分析器来调试内存泄漏。 它一直警告我:
内存碎片可能导致.NET保留太多的空闲内存。
或者
内存碎片会影响可以分配的最大对象大小。
因为我有强迫症,必须解决这个问题。
有什么标准编码实践可以帮助避免内存碎片?能否通过某些.NET方法进行碎片整理?这样做是否有帮助?
我正在使用Red Gates ANTS内存分析器来调试内存泄漏。 它一直警告我:
内存碎片可能导致.NET保留太多的空闲内存。
或者
内存碎片会影响可以分配的最大对象大小。
因为我有强迫症,必须解决这个问题。
有什么标准编码实践可以帮助避免内存碎片?能否通过某些.NET方法进行碎片整理?这样做是否有帮助?
你知道,我对这里的内存分析工具有些怀疑。.NET中的内存管理系统实际上通过移动内存来尝试为您整理堆(这就是为什么您需要固定内存才能与外部DLL共享它的原因)。
长时间占用大量内存的情况容易导致更多的内存碎片。而在.NET中,小的暂时性(短期)内存请求不太可能引起内存碎片。
这里还有一些值得思考的问题。在当前的.NET GC中,接近时间分配的内存通常会在空间上紧密排列,这与内存碎片相反。也就是说,您应该按照访问方式分配内存。
它是仅受管理代码控制还是包含诸如P / Invoke、非托管内存(Marshal.AllocHGlobal)或类似GCHandle.Alloc(obj,GCHandleType.Pinned)的内容?
GC堆对大对象分配进行了不同的处理,它不会将它们压缩,而是像传统的非托管内存存储一样,只是合并相邻的空闲块。
更多信息请参见: http://msdn.microsoft.com/en-us/magazine/cc534993.aspx
因此,对于非常大的对象,最好的策略是分配它们一次,然后保留它们并重复使用。
double[]
都会被强制进入LOH。将double[1024]
分配为三个4096字节的块会非常浪费。当然,我的真正怀疑是分配一个double[1024]
本来就不是一个好主意。 - supercat.NET Framework 4.5.1可以在垃圾回收期间明确地压缩大对象堆(LOH)。
GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;
GC.Collect();
请参阅GCSettings.LargeObjectHeapCompactionMode获取更多信息。