我在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#代码要快得多?
答案 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 /编译器每秒可以进行多少次紧密循环迭代。