Оптимизация компилятора C # для целей тестирования - PullRequest
4 голосов
/ 29 июня 2011

Мне нужно было проверить производительность какого-то .NET API, и я придумал этот код.

Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < 1000; i++) {
    int res = (int) SOME .NET FUNCTION TO RUN;
}
sw.Stop();
double time = sw.Elapsed.TotalMilliseconds;

При второй мысли я боялся, что компилятор оптимизирует все операции, так как res нигде не используется. И я изменил код следующим образом.

Stopwatch sw = Stopwatch.StartNew();
long sumIt = 0;
for (int i = 0; i < 1000; i++) {
    int res = (int) SOME .NET FUNCTION TO RUN;
    sumIt += res;
}
sw.Stop();
double time = sw.Elapsed.TotalMilliseconds;
value = (int) sumIt / 1000;

Интересно, что не похоже, что компилятор не оптимизирует работу с моим первым примером. Я тестировал csc (Visual Studio) и mono.

А вот и мои вопросы.

  • Безопасно ли делать тест в качестве моего первого примера?
  • Разве компилятор C # не достаточно умен, чтобы понять, что часть кода можно оптимизировать? Или есть какой-либо параметр компилятора для этого?

ДОБАВЛЕНО

SOME FUNCTION TO RUN на самом деле SOME .NET FUNCTION TO RUN, и я изменил ОП. И, основываясь на ответах, похоже, что компилятор C # не может (или не может) оптимизировать операцию, поскольку .NET FUNCTION TO RUN может иметь побочный эффект.

1 Ответ

2 голосов
/ 29 июня 2011

Компилятор (JIT) может оптимизировать вызов всей функции, если обнаружит, что у него нет побочных эффектов. Вероятно, должна быть возможность встроенной функции, чтобы обнаружить это.

Я пробовал небольшую функцию, которая действует только на входные аргументы, и вижу, что она оптимизирована путем проверки результирующей сборки (обязательно попробуйте Release build, не отмечая опцию «Поддерживает оптимизацию при загрузке модуля»).

 ...
 for (int i = 0; i < 1000; i++) 
 {    
    int res = (int) Func(i);
 }
 ...

 static int Func(int arg1)
 {
    return arg1 * arg1;
 }

Демонтажные:

      for (int i = 0; i < 1000; i++) 
    00000016  xor         eax,eax 
    00000018  inc         eax 
    00000019  cmp         eax,3E8h 
    0000001e  jl          00000018 
        }
...