【问题标题】:How does heap compaction work quickly?堆压缩如何快速工作?
【发布时间】:2010-05-16 04:46:50
【问题描述】:

他们说压缩垃圾收集器比传统的内存管理更快,因为它们只需要收集活动对象,并且通过在内存中重新排列它们以便所有内容都在一个连续的块中,最终不会产生堆碎片。但是如何快速完成呢?在我看来,这相当于装箱问题,即NP-hard,在我们目前对计算的了解范围内,无法在合理的时间内在大型数据集上完成。我错过了什么?

【问题讨论】:

  • 我经常想知道这一点。 Mono 没有碎片整理垃圾收集器来压缩堆,但 Microsoft 的 .NET 有。他们是怎么做到的?
  • 压缩不是装箱:在装箱中,必须回答“是否有可能用这些块中的一些块完全填充这个空间?”。压缩 GC 没有这样的问题,压缩通常与实时内存的大小成线性关系。
  • @Callum Rogers 一种方法是:第 1 阶段 - 就地反转所有指针,以便孩子指向他们的父母。阶段 2 - 将具有最低地址的活动块移动到堆的最开始。使用倒置指针更新所有父母。在第一个之后移动具有最低地址的第二个活动块......第 3 阶段 - 再次反转所有指针。

标签: algorithm garbage-collection


【解决方案1】:

压缩意味着在 RAM 中移动对象,以便删除一些对象(死对象,GC 应该回收的对象)并且所有剩余的对象在 RAM 中变得连续。

大多数压缩 GC 的工作方式是在从操作系统获得的单个连续区域内分配对象。压实就像移除死对象,然后将所有剩余的活对象“向左”推,挤出洞。如果 GC 通过压缩工作,那么分配只是向上移动“分配区域结束”指针的问题。综合而言,在分配区域内,有一个指针,使得空闲区域由该指针之后的字节组成。要为对象分配空间,只需将指针向上移动新的对象大小即可。有时,GC 决定是时候运行了,检测到死对象,挤出空洞,从而降低分配指针。

压缩 GC 带来的性能提升来自多个来源:

  • 对于分配,无需找到合适的“洞”:根据构造,空闲空间始终是一个单一的大区域,只需向上移动指针即可。
  • 没有碎片:压缩将所有活动对象一起移动,但这可以看作是将所有一起移动到一个大的空闲空间中。
  • 改进了局部性。通过将活动对象移动到相邻区域,可以改善与高速缓存有关的行为。特别是,压缩算法倾向于将对象保持在它们各自的分配顺序中(对象滑动但不交换),据报道这对大多数应用程序具有启发式作用。

如果操作系统拒绝提供单个分配区域,而是产生几个块,那么事情会变得有点复杂,并且可能开始看起来像装箱问题,因为压缩然后 GC 必须决定每个活动对象在哪个块中。然而,装箱的复杂性在于在一般情况下找到“完美”匹配;对于内存分配器来说,一个近似的解决方案已经足够了。

压缩算法的算法难点在于更新所有指针,使它们指向新的对象位置。通过严格类型,.NET 虚拟机可以明确地确定 RAM 中的每个单词是否是指针,但是在不使用过多额外 RAM 的情况下有效地更新所有指针可能会很棘手。 H.B.M. Jonkers 在“A Fast Garbage Compaction Algorithm”(Information Processing Letters,第 9 卷,第 1 期,1979 年,第 26-30 页)中描述了一个非常聪明的算法。我在 Vast Internet 上找不到该论文的副本,但该算法在 Jones 和 Lins 的 "Garbage Collection" 书中有所描述(第 5.6 节)。我向所有有兴趣了解垃圾收集器的人热烈推荐这本书。 Jonkers 的算法需要对活动对象进行两次线性传递,结果证明很容易实现(几十行代码,仅此而已;最困难的部分是理解它的工作原理)。

额外的复杂性来自世代收集器,它们在大多数情况下试图让大多数对象保持不变,只优先处理年轻对象。在这里,这意味着只压缩堆的末端;完全压实很少应用。这里的要点是,完全压缩虽然是线性的,但仍可能导致明显的停顿。分代 GC 试图使这种暂停更少。再说一次,琼斯和林斯的书是必读的。

【讨论】:

  • 我相信您可以通过将语言中的引用实现为指向指针表的指针来实现简单的压缩 GC,以便在压缩后 GC 只需要更新表。这使得每次取消引用都是双重取消引用,并且需要额外的表格空间。
  • Joseph:这实际上经常使用所谓的资源完成,即内核端分配。至少经典的 mac os 是这样做的。
  • “句柄”一词也与地址查找表相关。
  • 当活动对象被另一个活动对象引用时,压缩如何工作。被引用对象的重新映射是如何发生的?
  • 但是“移动对象”是如何工作的呢?您必须更新对移动对象的所有引用吗?
猜你喜欢
  • 1970-01-01
  • 2019-01-22
  • 2023-03-09
  • 2010-10-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-16
  • 1970-01-01
相关资源
最近更新 更多