关闭D垃圾收集器

问题描述 投票:24回答:4

我是一名C ++程序员,考虑将D用于我想要玩的个人项目。我想知道是否有办法完全禁用垃圾收集器,以及这样做的风险是什么。

我知道我可以通过覆盖new和delete来管理我自己的内存以使用malloc和free,但如果我这样做,我宁愿垃圾收集器根本不运行。

memory memory-management d garbage-collection
4个回答
41
投票

要在D2中关闭GC:

import core.memory;

void main(string[] args) {
    GC.disable;
    // Do stuff.
}

如果使用D1 / Phobos:

import std.gc;

void main(char[][] args) {
    std.gc.disable;
    // Do stuff.
}

在D1 / Tango中:

import tango.core.Memory;

void main(char[][] args) {
    GC.disable;
    // Do stuff.
}

可以通过调用GC.enable(D2或D1 / Tango)或std.gc.enable(D1 / Phobos)来类似地重新启用GC。这些可以在程序中的任何一点完成。在内部,使用计数器,并且为了实际重新启用GC,每次调用disable()时都必须调用enable()一次。

以下是一些与GC禁用无关的事情,因为它们会导致内存泄漏:

  1. 不要使用数组append(〜=)运算符,或使用.length属性放大已分配的数组。如果必须重新分配,这些依赖于GC来释放旧数组,因为程序中的其他地方可能存在别名。
  2. 不要使用内置关联数组。解决这些问题的唯一方法是通过GC。
  3. 大多数Phobos和我相信Tango的设计都假设存在垃圾收集。如果不使用GC,这些库中的函数可能会泄漏内存。
  4. 禁用GC时不要使用D2闭包。 (不管怎么说,对于一场比赛,你不会这么做。)

也就是说,虽然D被设计为可以在几个关键代码中禁用GC(存在实时约束的关键部分,你可能不应该使用任何形式的malloc而不是为实时设计无论如何计算,它主要是在假设GC存在的情况下设计的。在您的情况下,您仍然可以将GC用于所有初始化内容等,并且只有当您点击实际需要实时的游戏部分时才禁用它。

作为旁注,GC和手动内存管理可以在D中共存,并且在实践中,在优化代码时,手动删除具有微不足道的生命周期的一些大对象可以导致显着的加速。这可以使用delete语句与C ++类似地完成,即使启用了GC也可以安全地执行此操作。当您没有实时约束时,这将为您提供GC的大部分优势,具有大多数手动内存管理性能。


8
投票

如果你想使用malloc并免费使用std.c.stdlib。 GC永远不会触及这些。 std.gc拥有内存管理所需的所有东西,包括disable()。

GC并不是一件坏事。大多数(如果不是几乎所有D中的库)都会在代码中的某个地方没有明确删除内存,所以它不会让你成为一个英雄,让它永远关闭但是如果你有一些关键性能要求就可以了。

GC使得所有内容都更高效,如数组切片和在参数中创建新对象,而无需调用者在任何地方存储引用。良好的代码要少得多,GC代码变得更小。


1
投票

可以删除GC并用malloc / free周围的简单包装替换。


1
投票

我正在阅读关于D语言的文章,我在D中看起来很新的规格中找到了这个:

40.更好的C.

-betterC是dmd的命令行标志,它限制编译器对某些运行时功能的支持。值得注意的是,使用betterC编译的D程序或库与Druntime没有关联。编译时功能的使用不受任何限制。 https://dlang.org/spec/betterc.html

使用此命令行标志的结果之一是禁用GC和语言功能中继。

40.1后果

由于没有Druntime可用,许多D功能将无法使用。例如:

  • 垃圾收集
  • 线程本地存储
  • TypeInfo和ModuleInfo
  • 内置线程(例如core.thread)
  • 动态数组(但不是切片)和关联数组
  • 例外
  • 用字符串切换
  • 最后的开关
  • synchronized和core.sync
  • 静态模块构造函数或解构函数
  • 结构解构主义者
  • unittest(测试可以和-betterC标志一样)

另见https://dlang.org/blog/2017/08/23/d-as-a-better-c/

© www.soinside.com 2019 - 2024. All rights reserved.