2017-08-09 79 views
-6

我想了解在C#中完整地使用堆的完整工作。我理解堆栈和堆的工作方式,但是我没有发现堆碎片整理的任何解释(如果可能的话)。c#中的堆碎片整理?

当GC正在分配和释放堆上的内存块时,我读了很多关于碎片问题的文章。

所以,如果有人可以向我解释或提供一些关于此问题和堆(内存)碎片整理的好文章。

+0

从[CLR via C#]开始(https://blogs.msdn.microsoft.com/microsoft_press/2012/11/29/new-book-clr-via-c-fourth-edition/)。 –

回答

0

如果你知道堆的工作原理,我假设你知道有几种不同类型的堆。看到我的答案在这里 - Stack vs. Heap in .NET

所以你说的那两个我在那个答案中提到的是大对象堆(LOH)和GC堆(也称为Ephemeral堆)。

通常不需要担心.NET的堆碎片。用于.NET的GC工作分3步:标记,扫描,压缩。标记 - 扫描所有根源参考,并列出那些为根源的列表 - 这些列表不符合垃圾收集条件,不会被触及。扫描 - 清除不在列表中的项目的内存,并清除已标记项目的“标记位”。压缩 - 移动剩余的根目标对象的内存,使其位于连续的块中。紧凑阶段的一个警告是,LOH至少不是.NET 4.6.2的最新版本。这是CLR GC团队做出的设计决策,因为性能原因以及将所有内存移动到连续块的时间。从.NET 1.0开始,性能得到了很多改进,所以GC不是过去的野兽。在任何情况下,堆0,1和2 都是压缩。因此,不用担心那里的碎片。大部分情况下,LOH在其实现的算法中没有碎片问题而存活。有些情况下,你可以在LOH上分解。这可能是由几件事引起的 - 其中一些是错误的分配模式,频繁的Full GC集合等。这可以通过改善分配模式,尽可能地分配大块内存(以编程方式)和对象池来克服。

由于.NET 4.5.1中,有一个手动压缩蕙虽然我会强烈建议反对,理由是它是为您的应用巨大的性能命中原因有二道:

  1. 它很费时
  2. 它清除GC在应用程序的整个生命周期中收集的任何分配模式算法。在您的应用程序运行时,GC通过了解应用程序如何分配内存来调整自身。因此,它变得更有效率(到某个点),您的应用运行的时间越长。当你执行GC.Collect()(或任何它的重载)时,它会清除GC学到的所有数据 - 所以它必须重新开始。你可以阅读更多有关如何手动压缩这里蕙:https://blogs.msdn.microsoft.com/mariohewardt/2013/06/26/no-more-memory-fragmentation-on-the-net-large-object-heap/(再次,我建议反对)

信息关于GC标志,清扫,紧凑 - https://blogs.msdn.microsoft.com/abhinaba/2009/01/30/back-to-basics-mark-and-sweep-garbage-collection/

信息约LOH分配算法: https://www.red-gate.com/simple-talk/dotnet/net-framework/the-dangers-of-the-large-object-heap/