Оптимизация компилятора С# для целей бенчмаркинга

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

Stopwatch sw = Stopwatch.StartNew();
for (int i = 0; i < 1000; i++) {
 int res = (int) SOME .NET FUNCTION TO RUN;
}
sw.Stop();
****** 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();
****** time = sw.Elapsed.TotalMilliseconds;
value = (int) sumIt / 1000;

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

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

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

ADDED

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

1 ответ

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

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

...
 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 
 }

licensed under cc by-sa 3.0 with attribution.