garbage-collection - D 垃圾收集器 - 估计运行频率和运行时长?

标签 garbage-collection d

我正在学习 D 语言,我喜欢它的很多功能,但我对 GC 有点怀疑。我想给它机会,但首先我想知道:

  • 如何估计它运行的频率?
  • 它将运行多长时间?它是否与分配的内存量、托管对象的数量……成正比?

我特别询问当前 D2 运行时的 GC。

我知道 GC 在某些情况下可以带来更好的性能,但是这个例子呢: 想象一个游戏引擎在游戏开始时分配大量内存(数百兆字节的复杂结构),但在游戏运行时它几乎不进行任何分配/取消分配。但是有些事情仍然会发生(例如来自 GUI 中的字符串操作)——那些小事情最终会触发 GC,必须扫描所有分配的内存吗?据我了解,即使我决定自己管理大部分数据的内存,如果我希望它能够保存对托管内存(如字符串)的任何引用,我也必须将范围注册到 GC。

当然,我可以先编程然后再分析,但我希望至少能够提前对性能做出一些估计。比以后求助于一些解决方法要好。 (在我看来,像免费列表这样的解决方案是丑陋的解决方法,无论如何都不能使用。)

最佳答案

我没有确切的答案,但这是我能说的:

1) 最确定的来源是 gc 的源代码: https://github.com/D-Programming-Language/druntime/blob/master/src/gc/gc.d (我很确定 gcx.d 文件非常相似

2) 当你进行 gc 分配时,gc 可以预期运行(好吧,如果它认为它需要分配一个新 block ,那么它会首先尝试收集现有的东西,但根据我的经验,在实践中,最好假设每一个 new 都可以是一个 gc 集合),在程序终止时,而不是其他任何地方——如果你不分配 gc 内存,gc 实际上不会做任何事情。它不会阻止您的程序随机运行。

不过,如果您不知道去哪里找,它可能看起来很随意。检查此页面的底部: http://dlang.org/garbage.html

最常让我感到困惑的是数组字面量:auto x = [1,2,3];是运行时gc分配!有相当多的 phobos 函数也进行 gc 分配,尽管不是全部。如果 phobos 函数返回一个数组(包括一个字符串),它分配的可能性很高 - 如果不出意外,返回值可能是一个新 block ,除非你知道你传递给它一个缓冲区来接收数据。

也就是说,phobos 的大部分实际上是免费分配的,并且随着每个版本的发布而变得更好。我相信所有 std.algorithm 和 std.digest 包现在都是免费分配的,等等。所以你不必把它全部扔掉,只需要知道要避免哪些功能。

如果您编写了一个程序并想要找到隐藏的分配,我会使用调试器。在主循环之前设置一个断点。然后在gc_malloc 和gc_qalloc 处设置断点并继续。如果它中断,获取堆栈跟踪,现在您知道以后要避免什么。

如果您的主循环是免费的 gc 分配,它也将是免费的 gc 收集。

3) gc 会扫描所有内存吗?不必要。有一个 noscan 标志表明 gc 实现(参见源代码中的 mark 函数)可以跳过 block 。在druntime/src/rt/lifetime.d中,可以看到这个(这里叫做BlkAttr.NO_SCAN)是根据TypeInfo设置的。这不是很精确,但我很确定它在诸如大数组分配之类的事情上设置正确。不应扫描您游戏的批量数据 Assets 。

因此,它花费的时间与它实际扫描的内存量成正比,这可能比您分配的内存量少很多。

关于garbage-collection - D 垃圾收集器 - 估计运行频率和运行时长?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19978868/

相关文章:

Java 终结器 : An acceptable use-case?

java - 应用程序关闭时 JVM 垃圾收集器是否运行?

javascript - 从数组中提取子数组的内存最安全方法

Java 垃圾收集 GcInfo.getDuration() 将单位从毫秒更改为微秒

reflection - 在 D 中透明地同步对象中的任意属性

d - 从字符串混合中调用函数引用

time - 快速的跨平台计时器?

java - 幸存者空间已满可以触发完整GC吗?

d - 什么是惯用的(又名 "right")方法将整数集(或至少列表)作为 D 中的模板参数传递?