垃圾收集器的替代品

chr*_*ris 14 language-agnostic garbage-collection memory-management

我想知道垃圾收集器的最佳替代品,它的优点和缺点.我的首要任务是速度,记忆不那么重要.如果有垃圾收集器没有任何暂停,请告诉我.

我正在研究一种安全的语言(即没有悬空指针的语言,检查边界等),并且必须使用垃圾收集或其替代方案.

mik*_*era 15

我怀疑你最好坚持使用垃圾收集(按照JVM),除非你有一个非常好的理由.现代GC非常快速,通用且安全.除非您可以设计语言以利用特定的特殊情况(如上述分配器之一),否则您不太可能击败JVM.

我现在认为反对现代GC的唯一真正令人信服的理由是由于GC暂停导致的延迟问题.这些很小,很少见,并且对于大多数用途来说并不是真正的问题(例如,我已经成功地用Java编写了3D引擎),但它们仍然可以在非常紧凑的实时情况下引起问题.

话虽如此,可能仍然存在一些特殊情况,其中不同的内存分配方案可能有意义所以我在下面列出了一些有趣的选项:

非常快速,专门的内存管理方法的一个例子是许多游戏中使用的"每帧"分配器.这通过递增单个指针来分配内存来工作,并且在一个时间段结束时(通常是视觉"帧"),通过简单地将指针设置回基址并在下一次分配中覆盖它们,一次性丢弃所有对象. .这可能是"安全的",但对象寿命的限制将非常严格.如果您可以保证所有内存分配的大小有限并且仅对处理范围(例如单个服务器请求)有效,则可能是胜利者.

另一种非常快速的方法是为不同类别的对象提供专用对象池.释放的对象可以在池中循环使用,类似于自由对象槽的链接列表.操作系统通常将这种方法用于通用数据结构.但是,您需要再次观察对象生存期并通过将对象返回到池来显式处理处理.

引用计数看起来很好,但通常没有意义,因为每当更改指针值时,您经常需要取消引用并更新两个对象的计数.这种成本通常比具有简单和快速内存管理的优势更糟糕,并且在存在循环引用的情况下也不起作用.

堆栈分配非常快,可以安全运行.根据您的语言,可以在没有堆的情况下完成并完全在基于堆栈的系统上运行.但是我怀疑这会限制你的语言设计,所以这可能是一个非首发.某些DSL仍然值得考虑.

经典的malloc/free非常快,如果您对对象创建和生命周期有足够的限制,您可以使用您的语言强制执行.例如,如果您对指针的使用设置了重要约束.

无论如何 - 希望这是有用的思考!

  • @jer:这些发展增加了参考计数与其他技术来检测周期.所以它们不只是引用计数.特别是,他们很快就牺牲了引用计数可能最引人注目的优点:简单性. (3认同)
  • @Jon Harrop:嗯,公平地说,检测周期不是火箭科学. (2认同)

Tho*_*nin 5

如果速度很重要而内存不重要,那么最快和最简单的分配策略就是永不释放。分配只是一个向上碰撞指针的问题。你不能比这更快。

当然,从不释放任何东西都有可能导致可用内存溢出。记忆真的“不重要”是非常罕见的。通常有大量但有限的可用内存。一种策略称为“基于区域的分配”。也就是说,您使用指针碰撞策略在称为“区域”的几个大块中分配内存。释放只发生在整个区域。如果手头的问题可以被构造成连续的“任务”,每个任务都有自己的区域,那么这种策略可以取得一定的成功。

对于更通用的解决方案,如果您想要实时分配(即对分配请求的响应时间有保证的限制),那么垃圾收集就是要走的路。实时 GC 可能看起来像这样:使用指针碰撞策略分配对象。此外,在每次分配时,分配器都会执行一点垃圾收集,其中“活动”对象被复制到其他地方。在某种程度上,GC 与应用程序“同时”运行。这意味着访问对象需要一些额外的工作,因为您无法在保持“实时”承诺的同时移动对象并更新所有指针以指向新的对象位置。解决方案可能意味着障碍,例如一个额外的间接。分代 GC 允许对大多数对象进行无障碍访问,同时将暂停时间保持在严格的界限内。

对于想要研究内存分配,特别是垃圾收集的人来说,这篇文章是必读的。