【发布时间】:2015-02-21 09:24:09
【问题描述】:
我读到 GC(垃圾收集器)出于性能原因在堆中移动数据,我不太明白为什么,因为它是随机存取内存,也许是为了更好的顺序访问,但我想知道堆栈中的引用是否会在这种情况下更新一个移动发生在堆中。但也许偏移地址保持不变,但数据的其他部分被垃圾收集器移动,我不确定。
我认为这个问题与实现细节有关,因为并非所有垃圾收集器都可以执行此类优化,或者他们可能会这样做但不会更新引用(如果这是垃圾收集器实现中的常见做法)。但我想得到一些特定于 CLR(公共语言运行时)垃圾收集器的整体答案。
我还在阅读 Eric Lippert 的“引用不是地址”文章here,下面的段落让我有点困惑:
如果您认为引用实际上是一个不透明的 GC 句柄,那么 很明显,要找到与句柄关联的地址 你必须以某种方式“修复”对象。你必须告诉 GC “直到 进一步注意,不得将带有此句柄的对象移入 内存,因为有人可能有一个指向它的内部指针”。(那里 有多种方法可以做超出本文范围的事情 熨平板。)
听起来对于引用类型,我们不希望移动数据。那么我们在堆中还存储了什么,我们可以移动它们以进行性能优化?也许我们存储在那里的类型信息?顺便说一句,如果您想知道那篇文章是关于什么的,那么 Eric Lippert 正在比较引用和指针,并尝试解释说引用只是地址可能是错误的,即使它是 C# 实现它的方式。
另外,如果我上面的任何假设是错误的,请纠正我。
【问题讨论】:
-
如果我没记错的话,是的。 GC 中有一个“重定位”阶段,它移动所有对象以删除/减少内存碎片,在这个阶段,对移动对象的引用得到更新。我会尝试从 Channel9(或者可能来自 MSDN 文章)中找到链接,并将更新此评论。编辑:这是链接:msdn.microsoft.com/en-us/library/…(看看搬迁阶段)。
-
@AdamHouldsworth:但我的问题是了解这是如何发生的:当整个对象移动到其他一些内存地址时,它是否通过更新它们来维护引用值,或者只是不移动初始地址对象数组,以便它不需要更改参考值。
-
@kha:您的链接将不胜感激!谢谢。
-
@Tarik 确实,这就是我没有发布答案的原因。我也在等答案。
-
另一个更详细的链接(我认为您无法获得比这更多的详细信息):informit.com/articles/article.aspx?p=1409801&seqNum=2这是您可能会觉得有趣的一点:
When the garbage collection occurs, the memory occupied by objects B and D is reclaimed,which leads to gaps on the managed heap. To remove these gaps, the garbage collector compacts the remaining live objects (Obj A, C, and E) and coalesces the two free blocks (used to hold Obj B and D) into one free block. Lastly, the current allocation pointer is updated as a result of the compacting and coalescing
标签: c# .net garbage-collection heap-memory