D与C ++性能差异的解释

时间:2011-04-30 13:26:17

标签: c++ d

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。

2 个答案:

答案 0 :(得分:4)

你主要测量三个不同之处:

  1. gcc和dmd
  2. 生成的代码之间的差异
  3. 使用GC分配的额外时间。
  4. 分配课程所需的额外时间。
  5. 现在,您可能认为第2点无效,因为您使用了GC.disable();,但这只会使GC不会像往常一样收集。它不会使GC完全消失并自动将所有内存分配重定向到C的malloc。它仍然必须完成它通常做的大部分工作,以确保GC知道分配的内存,并且所有这些都需要时间。通常,这是程序执行中相对无关紧要的部分(甚至忽略了GC提供的好处)。但是,您的基准测试使其成为夸大此效果的整个程序。

    因此,我建议您考虑对您的方法进行两处更改:

    1. 切换到使用gdc与gcc进行比较或切换到dmc以与dmd进行比较
    2. 使程序更具等效性。要么D和C ++都在堆上分配结构,要么至少要使它在不触及GC的情况下进行分配。如果你正在优化程序以获得最大速度,那么无论如何,你都会使用结构和C的malloc。
    3. 我甚至建议第三次改变:因为你对最高性能感兴趣,你应该尝试完全提出一个更好的程序。为什么不切换到结构并让它们在内存中连续定位?这将使分配(实质上是整个程序)尽可能快。

      使用上面使用dmd&amp; amp;运行的代码我的机器上的dmc导致以下时间:

      • DMC 8.42n(无标志):~880ms
      • DMD 2.062(无标志):~1300ms

      将代码修改为以下内容:

      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导致以下时间:

      • DMC 8.42n(无标志):~95ms + - 20ms
      • DMD 2.062(无标志):~95ms + - 20ms

      基本上,相同(我必须开始使用一些统计数据来更好地了解哪一个真正更快,但在这个规模上,它是无关紧要的)。请注意,使用它比使用这种策略要快得多,而且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);
    }
}