Я написал некоторый код для проверки влияния 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..
Когда я обертываю цикл for внутри Fibo() блоком try-catch следующим образом:
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: Отличный анализ Jon Skeet показывает, что попытка try-catch каким-то образом заставляет среду CLR x86 более выгодно использовать регистры процессора в этом конкретном случае (и Я думаю, нам еще предстоит понять, почему). Я подтвердил, что Джон обнаружил, что x64 CLR не имеет этой разницы и что он был быстрее, чем CLR x86. Я также тестировал с использованием типов int
внутри метода Fibo вместо типов long
, а затем CLR x86 был столь же быстрым, как и x64 CLR.
ОБНОВЛЕНИЕ: Похоже, эта проблема была устранена Roslyn. Такая же машина, такая же версия CLR - проблема остается такой же, как и при компиляции с VS 2013, но проблема исчезает при компиляции с VS 2015.