Ваш тест не совсем справедлив для версий, основанных на свойствах. JIT достаточно умен, чтобы встроить простые свойства, чтобы они имели производительность во время выполнения, эквивалентную производительности прямого доступа к полю, но он не кажется достаточно умным (сегодня), чтобы определять, когда свойства обращаются к постоянным значениям.
В вашем примере, весь цикл цикла версии с полевым доступом оптимизирован, и теперь становится:
for (int i = 0; i < loopCount; i++)
00000025 xor eax,eax
00000027 inc eax
00000028 cmp eax,989680h
0000002d jl 00000027
}
тогда как вторая версия фактически выполняет деление с плавающей запятой на каждой итерации:
for (int i = 0; i < loopCount; i++)
00000094 xor eax,eax
00000096 fld dword ptr ds:[01300210h]
0000009c fdiv qword ptr ds:[01300218h]
000000a2 fstp st(0)
000000a4 inc eax
000000a5 cmp eax,989680h
000000aa jl 00000096
}
Внесение всего лишь двух небольших изменений в ваше приложение, чтобы сделать его более реалистичным, делает две операции практически идентичными по производительности.
Во-первых, рандомизируйте входные значения, чтобы они не были константами, а JIT не был достаточно умен, чтобы полностью удалить деление.
Изменить с:
Point point = new Point(12.0, 123.5, 0.123);
до:
Random r = new Random();
Point point = new Point(r.NextDouble(), r.NextDouble(), r.NextDouble());
Во-вторых, убедитесь, что результаты каждой итерации цикла используются где-то:
Перед каждым циклом, рассчитать значение = 0, чтобы они оба начинались в одной и той же точке. После каждого цикла вызывайте Console.WriteLine (вычисленное значение.ТoString ()), чтобы убедиться, что результат «используется», чтобы компилятор не оптимизировал его. И, наконец, измените тело цикла с «selectedValue = ...» на «selectedValue + = ...», чтобы использовать каждую итерацию.
На моей машине эти изменения (при сборке релиза) дают следующие результаты:
Direct field access: 133
Property access: 133
Total difference: 0
Average difference: 0
Как и следовало ожидать, x86 для каждого из этих измененных циклов идентичен (за исключением адреса цикла)
000000dd xor eax,eax
000000df fld qword ptr [esp+20h]
000000e3 fmul qword ptr [esp+28h]
000000e7 fdiv qword ptr [esp+30h]
000000eb fstp st(0)
000000ed inc eax
000000ee cmp eax,989680h
000000f3 jl 000000DF (This loop address is the only difference)