为什么D中的循环比C#中的循环慢得多?

时间:2013-12-29 04:25:41

标签: c# performance benchmarking d

我在C#和D中有以下两段代码,目标是在一个简单的循环中比较速度。

d

import std.stdio;
import std.datetime;

void main() {
    StopWatch timer;
    long summer = 0;
    timer.start();
    for (long i = 0; i < 10000000000; i++){
        summer++;
    }
    timer.stop();
    long interval_t = timer.peek().msecs;
    writeln(interval_t);
}

输出:约30秒

C#:

using System;
using System.Diagnostics;

class Program{
    static void Main(){
        Stopwatch timer = new Stopwatch();
        timer.Start();
        long summer = 0;
        for(long i = 0; i < 10000000000; i++){
            summer++;
        }
        timer.Stop();
        Console.WriteLine(timer.ElapsedMilliseconds);
    }
}

输出:约8秒

为什么C#代码要快得多?

3 个答案:

答案 0 :(得分:11)

还有一点不仅仅是说:“你没有打开优化器。”

至少在猜测时,你没有(最初)在 情况下打开优化器。尽管如此,未启用优化的C#版的运行速度几乎与使用优化的D版一样快。为什么会这样?

答案源于编译模型的差异。 D执行静态编译,因此源被转换为包含机器代码的可执行文件,然后执行。发生的唯一优化是在静态编译期间完成的任何操作。

相比之下,C#从源代码转换为MSIL,一种中间语言(即,基本上是字节码)。然后由内置于CLR的JIT编译器(公共语言运行库 - Microsoft的MSIL虚拟机)将其转换为机器语言。您可以在运行C#编译器时指定优化。这只是在从源代码到字节代码进行初始编译时控制优化。当您运行代码时,JIT编译器会做它的事情 - 无论您是否在从源代码到字节代码的初始转换中指定优化,它都会进行优化。这就是为什么当你没有用任何一个指定优化时,使用C#获得比使用D更快的结果。

然而,我觉得有必要补充一下,你得到的两个结果(D和C#分别为7秒和8秒)非常糟糕。一个不错的优化器应该认识到最终输出根本不依赖于循环,并且基于它应该完全消除循环。仅仅为了比较,我做了(约)我能做的最简单的C ++翻译:

#include <iostream>
#include <time.h>

int main() {
    long summer = 0;
    auto start = clock();
    for (long i = 0; i < 10000000000; i++)
        summer++;
    std::cout << double(clock() - start) / CLOCKS_PER_SEC;
}

使用cl /O2b2 /GL编译VC ++,这始终显示时间为0。

答案 1 :(得分:7)

我相信你的问题应该标题为:

  

为什么由&lt; 编译的for循环在这里插入你的D编译器&gt;比在&lt; 编译的循环慢得多,在这里插入C#编译器/运行时&gt;?

不同实现的性能可能会有很大差异,而且不是语言本身的特征。您可能正在使用DMD,即参考D编译器,它不知道使用高度优化的后端。为获得最佳性能,请尝试使用GDC或LDC编译器。

您还应该发布您使用的编译选项(可能只使用一个编译器启用了优化)。

有关详细信息,请参阅此问题: How fast is D compared to C++?

答案 2 :(得分:2)

有几个答案表明优化器会优化整个循环。

大多数情况下,他们明确这样做,因为他们希望程序员将循环编码为定时循环。

这种技术通常用于硬件驱动程序,等待的时间比设置定时器和处理定时器中断所用的时间短。

这是在Linux启动时计算“bogomips”的原因...要校准这个特定的CPU /编译器每秒可以进行多少次紧密循环迭代。