2

我在 Unity 的Boehm–Demers–Weiser 垃圾收集器上运行,它是一种非分代 GC。

我在内存中有一大棵托管对象树(~100k 个对象,~200MiB 分配)。

这些对象本质上是一个缓存并且永远不会超出范围,因此它们实际上永远不会被 GC 清除。

然而,因为 Boehm 是非代际的,所以这个陈旧的缓存永远不会被提升到更高的代。这会导致标记阶段花费大量的处理时间,因为它必须在每个集合上遍历整个缓存,从而导致明显的延迟峰值。

正如 Unity 文档所说,这是“设计使然” :

至关重要的是,Unity 的垃圾收集(使用 Boehm GC 算法)是非分代和非压缩的。“非分代”意味着 GC 在执行收集过程时必须扫描整个堆,因此其性能会随着堆的扩展而下降

我很清楚减少重复性垃圾分配的方法,但是我找不到有关如何在非分代 GC 中优化大型、陈旧的基线分配的任何信息。

进一步来说:

  • 有没有办法将根指针(例如静态字段)标记为完全被 GC 忽略?
  • 在标记阶段是否有一些数据结构模式可以更快地遍历?
  • 相反,是否存在阻碍标记阶段速度的已知数据结构模式?

这些问题只是我解决这个问题的一些假设,但我愿意接受所有建议。

4

1 回答 1

0

可以通过将程序启动与静态数据结构的初始化与稳态操作分开来近似世代行为。所有指向启动内存区域的指针都可以被忽略,而来自它的指针不应该存在,因为在切换点(将在 GC 控制下)分配之后没有分配任何内容。

甚至可以在切换到新区域之前对启动区域进行一次 GC。本质上,您最终会得到一种有限形式的基于区域的非移动收集器,其中区域之间的引用只发生在一个方向上。

于 2019-02-24T23:21:53.767 回答