2015-04-08 5 views
1

Я бегу очень простая программаПочему x86 JIT умнее, чем x64?

static void Main(string[] args) 
    { 
     Console.WriteLine(Get4S()); 
     Console.WriteLine(Get4()); 
    } 

    private static int Get4S() 
    { 
     return 4; 
    } 

    private static int Get4() 
    { 
     int res = 0; 
     for (int i = 0; i < 4; i++) 
     { 
      res++; 
     } 
     return res; 
    } 

, когда он работает под x86 он встраивает Get4S метод и Get4 ASM код:

00000000 push  ebp 
00000001 mov   ebp,esp 
00000003 xor   eax,eax 
00000005 inc   eax 
00000006 inc   eax 
00000007 inc   eax 
00000008 inc   eax 
00000009 pop   ebp 
0000000a ret 

НО при запуске под x64 мы получаем тот же ассемблер для Get4S метод, но Get4 asm не оптимизирован:

00000000 xor   eax,eax 
00000002 xor   edx,edx 
00000004 inc   eax 
00000006 inc   edx 
00000008 cmp   edx,4 
0000000b jl   0000000000000004 
0000000d ret 

Я предположил, что x64 JIT разворачивает цикл, а затем видит, что результат может быть вычислен во время компиляции, а функция с результатом компиляции будет включена. Но ничего из этого не случилось.

Почему x64 так глупо в этом случае? ..

+0

Включены ли jim opimizations? – CodesInChaos

+0

@CodesInChaos, конечно, вы видите, что x86-код оптимизирован. Это не оптимально, но он разворачивает цикл, это невозможно, когда оптимизация jit подавлена. –

+0

Не удалось воспроизвести. x64 JIT также оптимизирован для постоянной 4 для меня. Код выглядел так: http://pastebin.com/UEtXUsLA – harold

ответ

4

Я получил точку. Это связано с тем, что RyuJIT используется, когда выбрана сборка x64, даже если выбрана целевая платформа .Net 4.5.2. Таким образом, я установил его, добавив этот раздел в App.config файл:

<configuration> 
    <runtime> 
    <useLegacyJit enabled="1" /> 
    </runtime> 
</configuration> 

Эта разметка позволяет «устаревший» x64 JIT (в кавычках, потому что я думаю, что он намного лучше, чем «блестящий» RyuJIT), и результата ASM в Основным методом является:

00000000 sub   rsp,28h 
00000004 mov   ecx,4 
00000009 call  000000005EE75870 
0000000e mov   ecx,4 
00000013 call  000000005EE75870 
00000018 nop 
00000019 add   rsp,28h 
0000001d ret 

Оба метода были рассчитаны во время компиляции и в соответствии с их значениями.

Заключение: Когда установлен .Net 4.6, старый джиттер x64 заменяется на RyuJIT для всех решений под CLR4.0. Таким образом, единственный способ отключить это: useLegacyJit switch или COMPLUS_AltJit переменная окружения

+0

* потому что я думаю, что он намного лучше чем «блестящий» RyuJIT * Battle закаленный JIT работает лучше, чем неподдерживаемая предварительная версия: новости на 11. –

+0

@ ta.speot.is Я не говорю, что RyuJIT никогда не должен рождаться, я говорю, что Microsoft говорит «все , у нас есть новый uberfast JITter, вам понравится », но пока это не так. В будущем - может быть. Во всяком случае, я не вижу причин, по которым они решили основать RyuJIT на джиттере x86, когда x64 был умнее всеми способами (за исключением этой редкой ошибки с разворачиванием петли). –