D垃圾回收器 - 估计运行频率和时间?

3
我正在学习D语言,我喜欢它的许多特性,但我对其垃圾回收机制有些怀疑。我想先给它一个机会,但首先我想知道:
  • 如何估计它将运行多久?
  • 它的运行时间有多长?与分配的内存量、管理对象的数量等成比例吗?
我特别询问当前D2运行时中的GC。
我知道在某些情况下,GC可以提高性能,但是对于这个例子呢: 想象一下一个游戏引擎,在游戏开始时分配大量的内存(几百兆字节的复杂结构),但在游戏运行时,它几乎不进行任何分配/释放操作。但仍然会发生一些小的操作(例如GUI中的字符串操作)—那些小操作最终会触发GC扫描所有已分配的内存吗?据我所了解,即使我决定自己管理大部分数据的内存,如果我希望GC能够保存对托管内存(如字符串)的任何引用,我仍需要向GC注册范围。
当然,我可以先编程再进行剖析,但我希望能够提前对性能做出至少一些估计,这比以后寻找解决方法要好。(像自由列表这样的解决方案在我看来是丑陋的解决方法,并且无法在任何地方使用。)

1
你可以添加自己的垃圾回收器,它是现有垃圾回收器的副本,但会发出调试信息。 - ratchet freak
1
这可能是可行的,但那只是一种对现有程序进行分析的方法。我想要了解的是 D GC 的一般时间复杂度。因此,在我开始编写一些更大的 D 程序之前,我可以事先决定是否可以放心地将 GC 用于所有内容,或者是否应该更好地自己管理一些内存 - 在这种情况下,如何做才能真正帮助自己。 - michalsrb
2个回答

3
我没有确切的答案,但是我可以说一下:
1)最可靠的来源应该是gc的源代码: https://github.com/D-Programming-Language/druntime/blob/master/src/gc/gc.d (我很确定非常相似的gcx.d文件)
2)当您进行gc分配时,可以期望运行gc(如果它认为需要分配新块,则会尝试先收集现有内容,但根据我的经验,在实践中,最好假设每个新对象都可能是gc收集),在程序终止时以及其他任何地方 - 如果您不分配gc内存,则gc实际上不会执行任何操作。它不会随机停止您的程序运行。
尽管如果您不知道要查找哪里,它可能看起来很随机。请检查此页面底部: http://dlang.org/garbage.html 最常让我困扰的是数组字面量:auto x = [1,2,3]; 是运行时gc分配!还有一些phobos函数也会进行gc分配,但并非全部。如果phobos函数返回一个数组(包括字符串),很可能会进行分配 - 除非您知道传递了一个缓冲区来接收数据,否则返回值可能是一个新块。
话虽如此,phobos的大部分实际上是无需分配的,并且每个版本都在不断改进。我相信现在std.algorithm和std.digest包中的所有内容都是无需分配的,还有其他一些包也是。因此,您不必将其全部抛弃,只需知道要避免哪些函数即可。
如果您编写了一个程序并想查找隐藏的分配,我建议使用调试器。在主循环之前设置断点。然后在gc_malloc和gc_qalloc处设置断点并继续。如果它中断了,获取堆栈跟踪,现在您就知道以后要避免什么了。
如果您的主循环没有进行gc分配,它也将不进行gc回收。

3) gc是否会扫描所有内存?不一定。gc实现中有一个noscan标志(请参见源代码中的mark函数),可以跳过某些块。在druntime/src/rt/lifetime.d中,您可以看到这个标志(在此处称为BlkAttr.NO_SCAN)是基于TypeInfo设置的。虽然这不是很精确,但我非常确定它已正确设置在大型数组分配等物品上。游戏的大量数据资产不应该被扫描。

因此,gc所需时间将与它实际扫描的内存量成比例,这可能比您分配的内存量少得多。


我查看了gcx.d和其他文件 - 我可能错过了很多东西,但我的第一印象很糟糕 - 它确实检查每个扫描区域的每个<指针大小>字节,并递归地进入托管数据的每个发现的指针...除了NO_SCAN之外,是的。但显然,TypeInfo_Class具有返回1的flags属性 - 即应该进行扫描。每个类都无条件扫描,还是编译器为每个具有基于其成员变量返回0/1的flags属性的类子类化? - michalsrb
可以为每个成员变量设置标志,但目前尚未完全实现。编译器生成子类类型信息,并且钩子在那里进一步扩展-对象_.d中的RTInfo-如果您自定义它,它对于许多其他用途也很有用,但库根本不使用它,它已经在编译器中实现,但在主库中已经设置为空了相当长的时间。 Rainer已经完成了大部分工作,使其更加精确,但它尚未集成到主树中。我不知道将其集成的时间表是什么样子。 - Adam D. Ruppe
话虽如此,扫描整个类并不一定是什么大问题,因为您的大量数据可能存储在数组中,并且将被标记为NO_SCAN,因此不会递归进入它们。我的dom.d有点占用内存,但Element类本身只有约64字节 - 大多数内存使用情况在于字符串引用。 - Adam D. Ruppe

1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接