Действительно ли перемещение объявления переменной вне цикла увеличивает производительность?

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

Есть ли вообще какое-либо преимущество в производительности

int smallPrime, spGen;

for (int i = 0; i < numSmallPrimes; i++)
{
    smallPrime = smallPrimes[i];
    spGen = spHexGen[i];

    [...]
}

через это?

for (int i = 0; i < numSmallPrimes; i++)
{
    int smallPrime = smallPrimes[i];
    int spGen = spHexGen[i];

    [...]
}

Компилятор это уже делает?


person jnm2    schedule 14.06.2011    source источник
comment
Возможный дубликат stackoverflow.com/questions/3241483/   -  person mdm    schedule 14.06.2011
comment
Этот ответ не объясняет, почему; это просто говорит нет. Для меня важно знать почему и что происходит внутри CLR. (И Гуффа это очень хорошо продемонстрировал.)   -  person jnm2    schedule 14.06.2011
comment
Что ваш профилировщик говорит вам о горячей точке? Сконцентрируйтесь на этом.   -  person Eric Lippert    schedule 14.06.2011
comment
Его заглушают тесты Рабина-Миллера - сначала мне нужно выполнить дополнительные настройки. Как оказалось, есть хороший ответ без настройки еще одного теста производительности.   -  person jnm2    schedule 14.06.2011
comment
Полностью согласен с @Eric. Мне кажется, читая ваш вопрос, что вы слепо ищете всевозможные оптимизации. Я хотел бы предупредить вас, так как это широко известно как потеря времени. Вместо этого запустите профилировщик (он должен быть в вашей среде C#) и найдите, где и как тратится время, а затем сконцентрируйтесь на нем, помня о правиле Парето 80/20.   -  person Offirmo    schedule 20.10.2011
comment
Хорошая точка зрения. Здесь, однако, я просто хочу иметь это в затылке, взять ли за привычку объявлять переменные так близко, как я хочу, или объявлять их вне циклов. Приятно знать, что мне не нужно беспокоиться об оптимизации здесь.   -  person jnm2    schedule 21.10.2011


Ответы (2)


Прироста производительности нет вообще.

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

Редактировать:

Чтобы убедиться, что разницы нет, я скомпилировал два случая и изучил сгенерированный машинный код, и он идентичен для двух случаев:

Объявление переменных вне цикла:

            for (int i = 0; i < numSmallPrimes; i++) {
00000000  push        ebp 
00000001  mov         ebp,esp 
00000003  sub         esp,14h 
00000006  mov         dword ptr [ebp-4],ecx 
00000009  mov         dword ptr [ebp-14h],edx 
0000000c  cmp         dword ptr ds:[004214A8h],0 
00000013  je          0000001A 
00000015  call        69133CFB 
0000001a  xor         edx,edx 
0000001c  mov         dword ptr [ebp-10h],edx 
0000001f  xor         edx,edx 
00000021  mov         dword ptr [ebp-0Ch],edx 
00000024  xor         edx,edx 
00000026  mov         dword ptr [ebp-8],edx 
00000029  xor         edx,edx 
0000002b  mov         dword ptr [ebp-10h],edx 
0000002e  nop 
0000002f  jmp         0000006D 
                smallPrime = smallPrimes[i];
00000031  mov         eax,dword ptr [ebp-10h] 
00000034  mov         edx,dword ptr [ebp-14h] 
00000037  cmp         eax,dword ptr [edx+4] 
0000003a  jb          00000041 
0000003c  call        69136F00 
00000041  mov         eax,dword ptr [edx+eax*4+8] 
00000045  mov         dword ptr [ebp-8],eax 
                spGen = spHexGen[i];
00000048  mov         eax,dword ptr [ebp-10h] 
0000004b  mov         edx,dword ptr [ebp+8] 
0000004e  cmp         eax,dword ptr [edx+4] 
00000051  jb          00000058 
00000053  call        69136F00 
00000058  mov         eax,dword ptr [edx+eax*4+8] 
0000005c  mov         dword ptr [ebp-0Ch],eax 
                Console.WriteLine(smallPrime + spGen);
0000005f  mov         ecx,dword ptr [ebp-8] 
00000062  add         ecx,dword ptr [ebp-0Ch] 
00000065  call        68819C90 
            for (int i = 0; i < numSmallPrimes; i++) {
0000006a  inc         dword ptr [ebp-10h] 
0000006d  mov         eax,dword ptr [ebp-10h] 
00000070  cmp         eax,dword ptr [ebp-4] 
00000073  jl          00000031 
            }
        }
00000075  nop 
00000076  mov         esp,ebp 
00000078  pop         ebp 
00000079  ret         4

Объявление переменных внутри цикла:

            for (int i = 0; i < numSmallPrimes; i++) {
00000000  push        ebp 
00000001  mov         ebp,esp 
00000003  sub         esp,14h 
00000006  mov         dword ptr [ebp-4],ecx 
00000009  mov         dword ptr [ebp-14h],edx 
0000000c  cmp         dword ptr ds:[006314A8h],0 
00000013  je          0000001A 
00000015  call        68FB3C5B 
0000001a  xor         edx,edx 
0000001c  mov         dword ptr [ebp-8],edx 
0000001f  xor         edx,edx 
00000021  mov         dword ptr [ebp-0Ch],edx 
00000024  xor         edx,edx 
00000026  mov         dword ptr [ebp-10h],edx 
00000029  xor         edx,edx 
0000002b  mov         dword ptr [ebp-8],edx 
0000002e  nop 
0000002f  jmp         0000006D 
                int smallPrime = smallPrimes[i];
00000031  mov         eax,dword ptr [ebp-8] 
00000034  mov         edx,dword ptr [ebp-14h] 
00000037  cmp         eax,dword ptr [edx+4] 
0000003a  jb          00000041 
0000003c  call        68FB6E60 
00000041  mov         eax,dword ptr [edx+eax*4+8] 
00000045  mov         dword ptr [ebp-0Ch],eax 
                int spGen = spHexGen[i];
00000048  mov         eax,dword ptr [ebp-8] 
0000004b  mov         edx,dword ptr [ebp+8] 
0000004e  cmp         eax,dword ptr [edx+4] 
00000051  jb          00000058 
00000053  call        68FB6E60 
00000058  mov         eax,dword ptr [edx+eax*4+8] 
0000005c  mov         dword ptr [ebp-10h],eax 
                Console.WriteLine(smallPrime + spGen);
0000005f  mov         ecx,dword ptr [ebp-0Ch] 
00000062  add         ecx,dword ptr [ebp-10h] 
00000065  call        68699BF0 
            for (int i = 0; i < numSmallPrimes; i++) {
0000006a  inc         dword ptr [ebp-8] 
0000006d  mov         eax,dword ptr [ebp-8] 
00000070  cmp         eax,dword ptr [ebp-4] 
00000073  jl          00000031 
            }
        }
00000075  nop 
00000076  mov         esp,ebp 
00000078  pop         ebp 
00000079  ret         4
person Guffa    schedule 14.06.2011
comment
Объем в этих двух случаях разный, поэтому вы противоречите сами себе. - person Kon; 14.06.2011
comment
@Kon: В чем я противоречу себе? - person Guffa; 14.06.2011

Не совсем, компилятор сделает эту оптимизацию за вас.

person Jorge Córdoba    schedule 14.06.2011
comment
На самом деле это не оптимизация, это просто то, как работают локальные переменные. - person Guffa; 14.06.2011