为什么在Delphi中循环比C#更快?

isa*_*isa 5 c# delphi

德尔福:


procedure TForm1.Button1Click(Sender: TObject);
var I,Tick:Integer;
begin
  Tick := GetTickCount();
  for I := 0 to 1000000000 do
    begin
    end;
  Button1.Caption := IntToStr(GetTickCount()-Tick)+' ms';
end;

C#:


private void button1_Click(object sender, EventArgs e)
        {
            int tick = System.Environment.TickCount;
            for (int i = 0; i < 1000000000; ++i)
            {
            }
            tick = System.Environment.TickCount - tick;
            button1.Text = tick.ToString()+" ms"; 
        }

德尔福提供大约515毫秒

C#给出大约3775毫秒

Cli*_*ord 29

Delphi被编译为本机代码,而C#被编译为CLR代码,然后在运行时进行翻译.那就是说C#确实使用了JIT编译,所以你可能期望时间更相似,但它不是给定的.

如果你可以描述你运行它的硬件(CPU,时钟速率)将是有用的.

我无法访问Delphi重复您的实验,但使用本机C++与C#和以下代码:

VC++ 2008

#include <iostream>
#include <windows.h>

int main(void)
{
    int tick = GetTickCount() ;
    for (int i = 0; i < 1000000000; ++i)
    {
    }
    tick = GetTickCount() - tick;
    std::cout << tick << " ms" << std::endl  ; 
}
Run Code Online (Sandbox Code Playgroud)

C#

using System;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            int tick = System.Environment.TickCount;
            for (int i = 0; i < 1000000000; ++i)
            {
            }
            tick = System.Environment.TickCount - tick;
            Console.Write( tick.ToString() + " ms" ) ; 
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我最初得到:

C++  2792ms
C#   2980ms
Run Code Online (Sandbox Code Playgroud)

然而,我然后在C#版本上执行了重建,<project>\bin\release<project>\bin\debug分别直接从命令行运行可执行文件.这产生了:

C# (release):  720ms
C# (debug):    3105ms
Run Code Online (Sandbox Code Playgroud)

所以我认为这就是差异真正存在的地方,你是从IDE运行C#代码的调试版本.

如果您认为C++特别慢,我将其作为优化版本构建运行并获得:

C++ (Optimised): 0ms
Run Code Online (Sandbox Code Playgroud)

这并不奇怪,因为循环是空的,并且控制变量不在循环外使用,因此优化器完全删除它.为了避免我声明ivolatile具有以下结果:

C++ (volatile i): 2932ms
Run Code Online (Sandbox Code Playgroud)

我的猜测是C#实现也删除了循环,而720ms来自其他东西; 这可以解释第一次测试中时间的大部分差异.

Delphi在做什么我无法分辨,你可能会看看生成的汇编代码.

所有上述测试均采用AMD Athlon双核5000B 2.60GHz,适用于Windows 7 32位.


Fra*_*ank 9

如果这是一个基准测试,那么这是一个非常糟糕的基准测试,因为在这两种情况下都可以优化循环,所以你必须查看生成的机器代码才能看到正在发生的事情.如果您使用C#的发布模式,请使用以下代码

 Stopwatch sw = Stopwatch.StartNew();
 for (int i = 0; i < 1000000000; ++i){ }
 sw.Stop();
 Console.WriteLine(sw.Elapsed);
Run Code Online (Sandbox Code Playgroud)

由JITter转换为:

 push        ebp 
 mov         ebp,esp 
 push        edi 
 push        esi 
 call        67CDBBB0 
 mov         edi,eax 
 xor         eax,eax               ; i = 0
 inc         eax                   ; ++i
 cmp         eax,3B9ACA00h         ; i == 1000000000?
 jl          0000000E              ; false: jmp
 mov         ecx,edi 
 cmp         dword ptr [ecx],ecx 
 call        67CDBC10 
 mov         ecx,66DDAEDCh 
 call        FFE8FBE0 
 mov         esi,eax 
 mov         ecx,edi 
 call        67CD75A8 
 mov         ecx,eax 
 lea         eax,[esi+4] 
 mov         dword ptr [eax],ecx 
 mov         dword ptr [eax+4],edx 
 call        66A94C90 
 mov         ecx,eax 
 mov         edx,esi 
 mov         eax,dword ptr [ecx] 
 mov         eax,dword ptr [eax+3Ch] 
 call        dword ptr [eax+14h] 
 pop         esi 
 pop         edi 
 pop         ebp 
 ret
Run Code Online (Sandbox Code Playgroud)


SLa*_*aks 7

TickCount不是一个可靠的计时器; 你应该使用.Net的Stopwatch课程.(我不知道Delphi的等价物是什么).

另外,您是否正在运行发布版本?
你有一个调试器吗?

  • 刚试过它.发布版本,没有调试器在我的机器上产生大约500毫秒.切换到调试版本或使用调试器(或两者)运行会产生大约4000毫秒.秒表和TickCount之间的区别是微不足道的. (4认同)
  • 如果我们每次有人在调试模式下"描述"一个.NET应用程序,并在Stack Overflow上发布有关其性能的问题...... (3认同)