有什么方法可以优化非世代GC的标记阶段?

时间:2019-02-22 16:23:25

标签: c# .net unity3d garbage-collection boehm-gc

我正在运行Unity的Boehm–Demers–Weiser garbage collector,这是一个非世代的GC。

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

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

但是,由于Boehm是非世代的,因此该陈旧的缓存永远不会移到更高的世代。这导致标记阶段要花费非常多的处理时间,因为它必须遍历每个集合的整个缓存,从而导致明显的滞后尖峰。

这是“故意设计的”,as the Unity documentation puts it

  

至关重要的是,使用Boehm GC算法的Unity的垃圾收集是非世代且紧凑的。 “非世代”意味着GC在执行收集过程时必须扫过整个堆,因此其性能会随着堆的扩展而降低

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

更具体地说:

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

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

1 个答案:

答案 0 :(得分:0)

通过将程序启动与静态数据结构的初始化与稳态操作分开,可以近似生成代行为。可以忽略进入启动内存区域的所有指针,但不应忽略来自该指针的指针,因为尚未分配在切换点之后(由GC控制)的任何内容。

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