我写了一些代码来测试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…——它实际上跑得更快!但为什么呢?
注意:我使用发行版配置编译了这个文件,并直接运行了EXE文件(在Visual Studio之外).
编辑:Jon Skeet's excellent analysis显示try-catch以某种方式导致x86CLR在此特定情况下以更有利的方式使用CPU寄存器(我认为我们还不知道原因).我确认了Jon的发现,即x64CLR没有这个区别,而且它比x86CLR更快.我还在FIBO方法中使用了int
个类型而不是long
个类型进行测试,然后x86CLR的速度与x64CLR一样快.
看起来这个问题已经被Roslyn解决了.同一台机器,同一个CLR版本——当使用VS 2013编译时,问题仍然存在,但当使用VS 2015编译时,问题消失了.