我正在阅读Steve Yegge的“动态语言反击”演讲,在其中他有点批评标记-清除垃圾收集(在该链接的5-10%处,“猪尝试飞行”幻灯片)。它们有什么问题?
我正在阅读Steve Yegge的“动态语言反击”演讲,在其中他有点批评标记-清除垃圾收集(在该链接的5-10%处,“猪尝试飞行”幻灯片)。它们有什么问题?
现代收集器(包括典型的分代收集器)是基于标记和复制的。其思想是,收集器跟踪“源区域”中的对象,将其复制到“目标空间”。完成后,“目标空间”的末尾会有一个连续的自由空间块,可用于分配新对象。“源区域”保留在一侧,以备下次垃圾收集器运行时使用。复制收集的好处在于,与垃圾对象相关联的垃圾收集成本接近于零。
分代收集器是一种具有多个空间(代)的收集器,这些空间以不同的速率进行收集。其基于“弱分代假设”,即大多数对象很快变得不可访问;即它们死得很快。因此,通过垃圾收集包含年轻对象的空间,您可以以相对较低的成本回收相对较大的空间。仍然需要收集较旧的代,但可能不需要那么频繁。
标记-清除垃圾收集器可以是分代的,但相比于复制式垃圾收集器,其效益并不那么显著。
mark-and-copy
是另一种与mark-sweep-compact
不同的策略。 - Preco Plusb以下是引语的背景:
我认为分代垃圾收集器是最好的答案,因为它可以减少暂停时间,而且说实话,所有新型动态语言的垃圾收集器都很糟糕。它们采用标记-清除或引用计数的方式。
从引语中可以看出,他在谈论相当原始的垃圾收集器,这些垃圾收集器不是分代的。分代垃圾收集器仍然可以采用标记和清除的方式,但大部分时间需要标记的对象较少,这使得它们比“每次都要标记整个世界”的标记和清除算法更快。
如果他的意思是这样的,我同意——但他本可以表达得更加清晰。请注意,这是一次演讲而不是博士论文——当场想出最清晰的表达方式有点棘手 :)
他将其与mark-compact进行对比:
对于这个问题,分代垃圾收集器是我得到的最好答案,因为它减少了暂停时间。坦白地说,所有新的动态语言的垃圾收集器都很糟糕。它们要么是标记-清除,要么是引用计数。
普通的标记和清除垃圾收集器并不好,因为它们存在堆碎片问题。在启用GC的语言中,高分配级别很常见,这通常比在C++中更快成为问题,因为许多对象只是存储在堆栈上。
话虽如此,紧凑型标记和清除垃圾收集器实际上就是将压缩处理加入其中的标记和清除垃圾收集器,因此术语可能需要更改。非压缩式收集器通常称为“保守式”以区分它们。