我今天一直在看D,从表面上看,它看起来很神奇。我喜欢它直接在语言中包含许多更高级别的构造,因此不必使用愚蠢的技巧或简洁的方法。如果 GC,我真正担心的一件事。我知道这是一个大问题,并且已经阅读了很多关于它的讨论。
我自己从一个问题中得出的简单测试表明 GC 非常慢。做同样事情的速度比直接的 C++ 慢 10 倍以上。(显然,测试并没有直接转换成现实世界,但性能影响是极端的,并且会减慢行为相似的现实世界发生(快速分配许多小对象)
我正在考虑编写一个实时低延迟音频应用程序,GC 可能会破坏应用程序的性能,使其几乎无用。从某种意义上说,如果它有任何问题,它将破坏实时音频方面,这更为重要,因为与图形不同,音频以更高的帧速率运行(44000+ vs 30-60)。(由于它的低延迟,它比可以缓冲大量数据的标准音频播放器更重要)
禁用 GC 将结果改进到 C++ 代码的 20% 以内。这很重要。我会在最后给出代码以供分析。
我的问题是:
- 用标准的智能指针实现替换 D 的 GC 以使依赖 GC 的库仍然可以使用是多么困难。如果我完全删除 GC,我将失去很多繁重的工作,因为与 C++ 相比,D 已经有限制库。
- GC.Disable 是否只是暂时停止垃圾收集(防止 GC 线程运行),而 GC.Enable 会从它停止的地方重新开始。因此,我可能会禁用 GC 在 CPU 使用率较高的情况下运行,以防止出现延迟问题。
- 有什么方法可以强制不始终使用 GC 的模式。(这是因为我没有在 D 中编程,当我开始编写不使用 GC 的眼镜时,我想确保我不会忘记实现自己的清理。
- 是否可以轻松更换D中的GC?(不是我想要,但有一天玩不同的 GC 方法可能会很有趣......这类似于我想的 1)
我想做的是用内存换取速度。我不需要每隔几秒钟运行一次 GC。事实上,如果我可以为我的数据结构正确实现自己的内存管理,那么它可能根本不需要经常运行。只有当内存变得稀缺时,我才可能需要运行它。不过,从我读过的内容来看,您等待调用它的时间越长,它就会越慢。由于通常在我的应用程序中有时我可以毫无问题地调用它,这将有助于减轻一些压力(但话又说回来,可能有几个小时我将无法调用它)。
我不太担心内存限制。我宁愿“浪费”内存而不是速度(当然,在一定程度上)。首先是延迟问题。
根据我的阅读,我至少可以走 C/C++ 的路线,只要我不使用任何依赖 GC 的库或语言结构。问题是,我不知道那些做的。我已经看到提到的字符串、新字符串等,但这是否意味着如果我不启用 GC,我就不能使用内置字符串?
我在一些错误报告中读到 GC 可能真的有错误,这可以解释它的性能问题吗?
另外,D 使用了更多的内存,实际上,D 在 C++ 程序之前就耗尽了内存。我想在这种情况下大约多出 15% 左右。我想那是给GC的。
我意识到以下代码不能代表您的普通程序,但它说的是当程序实例化很多对象时(例如,在启动时)它们会慢得多(10 倍是一个很大的因素)。GC 可能在启动时“暂停”,那么它不一定是一个问题。
如果我没有专门解除分配本地对象,如果我能以某种方式让编译器自动 GC 一个本地对象,那将是非常好的。这几乎是两全其美。
例如,
{
Foo f = new Foo();
....
dispose f; // Causes f to be disposed of immediately and treats f outside the GC
// If left out then f is passed to the GC.
// I suppose this might actually end up creating two kinds of Foo
// behind the scenes.
Foo g = new manualGC!Foo(); // Maybe something like this will keep GC's hands off
// g and allow it to be manually disposed of.
}
事实上,实际上能够将不同类型的 GC 与不同类型的数据相关联,并且每个 GC 都是完全自包含的,这可能会很好。这样我就可以根据我的类型定制 GC 的性能。
代码:
module main;
import std.stdio, std.conv, core.memory;
import core.stdc.time;
class Foo{
int x;
this(int _x){x=_x;}
}
void main(string args[])
{
clock_t start, end;
double cpu_time_used;
//GC.disable();
start = clock();
//int n = to!int(args[1]);
int n = 10000000;
Foo[] m = new Foo[n];
foreach(i; 0..n)
//for(int i = 0; i<n; i++)
{
m[i] = new Foo(i);
}
end = clock();
cpu_time_used = (end - start);
cpu_time_used = cpu_time_used / 1000.0;
writeln(cpu_time_used);
getchar();
}
C++ 代码
#include <cstdlib>
#include <iostream>
#include <time.h>
#include <math.h>
#include <stdio.h>
using namespace std;
class Foo{
public:
int x;
Foo(int _x);
};
Foo::Foo(int _x){
x = _x;
}
int main(int argc, char** argv) {
int n = 120000000;
clock_t start, end;
double cpu_time_used;
start = clock();
Foo** gx = new Foo*[n];
for(int i=0;i<n;i++){
gx[i] = new Foo(i);
}
end = clock();
cpu_time_used = (end - start);
cpu_time_used = cpu_time_used / 1000.0;
cout << cpu_time_used;
std::cin.get();
return 0;
}