D中的简单例子:
import std.stdio, std.conv, core.memory;
class Foo{
int x;
this(int _x){x=_x;}
}
void main(string args[]) {
GC.disable();
int n = to!int(args[1]);
Foo[] m= new Foo[n];
for(int i=0;i<n;i++){
m[i] = new Foo(i);
}
}
C ++代码:
#include <cstdlib>
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 = atoi(argv[1]);
Foo** gx = new Foo*[n];
for(int i=0;i<n;i++){
gx[i] = new Foo(i);
}
return 0;
}
没有任何编辑标记。
编译和运行:
>dmd td.d
>time ./td 10000000
>real 0m2.544s
C ++(gcc)中的Anlogue示例,运行:
>time ./tc 10000000
>real 0m0.523s
为什么呢?这么简单的例子,和如此大的区别:2.54s和0.52s。
答案 0 :(得分:4)
你主要测量三个不同之处:
现在,您可能认为第2点无效,因为您使用了GC.disable();
,但这只会使GC不会像往常一样收集。它不会使GC完全消失并自动将所有内存分配重定向到C的malloc。它仍然必须完成它通常做的大部分工作,以确保GC知道分配的内存,并且所有这些都需要时间。通常,这是程序执行中相对无关紧要的部分(甚至忽略了GC提供的好处)。但是,您的基准测试使其成为夸大此效果的整个程序。
因此,我建议您考虑对您的方法进行两处更改:
我甚至建议第三次改变:因为你对最高性能感兴趣,你应该尝试完全提出一个更好的程序。为什么不切换到结构并让它们在内存中连续定位?这将使分配(实质上是整个程序)尽可能快。
使用上面使用dmd&amp; amp;运行的代码我的机器上的dmc导致以下时间:
将代码修改为以下内容:
C ++代码:
#include <cstdlib>
struct Foo {
int x;
};
int main(int argc, char** argv) {
int n = atoi(argv[1]);
Foo* gx = (Foo*) malloc(n * sizeof(Foo));
for(int i = 0; i < n; i++) {
gx[i].x = i;
}
free(gx);
return 0;
}
D代码:
import std.conv;
struct Foo{
int x;
}
void main(string args[]) {
int n = to!int(args[1]);
Foo[] m = new Foo[](n);
foreach(i, ref e; m) {
e.x = i;
}
}
使用我的代码使用DMD&amp; DMC导致以下时间:
基本上,相同(我必须开始使用一些统计数据来更好地了解哪一个真正更快,但在这个规模上,它是无关紧要的)。请注意,使用它比使用这种策略要快得多,而且D同样能够使用此策略。在这种情况下,运行时差异可以忽略不计,但我们仍然保留了使用GC的好处,并且在编写D代码时可能出现的问题肯定要少得多(请注意您的程序如何失败{{1}它的所有分配?)。
此外,如果您绝对需要,D允许您通过delete
使用C的标准库。如果需要,这将允许您真正绕过GC并通过使用C的malloc实现最大性能。在这种情况下,没有必要,所以我在更安全,更易读的代码方面犯了错误。
答案 1 :(得分:2)
试试这个:
import std.stdio, std.conv, core.memory;
class Foo{
int x = void;
this(in int _x){x=_x;}
}
void main(string args[]) {
GC.disable();
int n = to!int(args[1]);
Foo[] m= new Foo[n];
foreach(i; 0..n){
m[i] = new Foo(i);
}
}