我编写了一些代码来测试 try-catch 的影响,但看到了一些令人惊讶的结果。
static void Main(string[] args)
{
Thread.CurrentThread.Priority = ThreadPriority.Highest;
Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.RealTime;
long start = 0, stop = 0, elapsed = 0;
double avg = 0.0;
long temp = Fibo(1);
for (int i = 1; i < 100000000; i++)
{
start = Stopwatch.GetTimestamp();
temp = Fibo(100);
stop = Stopwatch.GetTimestamp();
elapsed = stop - start;
avg = avg + ((double)elapsed - avg) / i;
}
Console.WriteLine("Elapsed: " + avg);
Console.ReadKey();
}
static long Fibo(int n)
{
long n1 = 0, n2 = 1, fibo = 0;
n++;
for (int i = 1; i < n; i++)
{
n1 = n2;
n2 = fibo;
fibo = n1 + n2;
}
return fibo;
}
在我的计算机上,这始终打印出 0.96 左右的值。
当我用 try-catch 块将 for 循环包装在 Fibo() 内时,如下所示:
static long Fibo(int n)
{
long n1 = 0, n2 = 1, fibo = 0;
n++;
try
{
for (int i = 1; i < n; i++)
{
n1 = n2;
n2 = fibo;
fibo = n1 + n2;
}
}
catch {}
return fibo;
}
现在它始终打印出 0.69...——它实际上运行得更快!但为什么?
注意:我使用 Release 配置编译它并直接运行 EXE 文件(在 Visual Studio 之外)。
EDIT: 乔恩·斯基特出色的分析表明在这种特定情况下,try-catch 在某种程度上导致 x86 CLR 以更有利的方式使用 CPU 寄存器(我认为我们还没有理解为什么)。我证实了 Jon 的发现,x64 CLR 没有这种差异,而且它比 x86 CLR 更快。我也测试过使用int
Fibo 方法中的类型而不是long
类型,然后 x86 CLR 与 x64 CLR 一样快。
UPDATE:看起来这个问题已经被 Roslyn 解决了。相同的机器,相同的 CLR 版本 - 使用 VS 2013 编译时问题仍然如上,但使用 VS 2015 编译时问题消失。