【问题标题】:Does moving variable declaration outside of a loop actually increase performance?将变量声明移到循环外实际上会提高性能吗?
【发布时间】:2011-09-14 16:16:32
【问题描述】:

我正在编写处理器密集型加密代码 (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];

    [...]
}

编译器是否已经这样做了?

【问题讨论】:

  • 那个答案没有解释为什么;它只是说不。对我来说,了解原因以及了解 CLR 内部发生了什么是很有价值的。 (而 Guffa 很好地证明了这一点。)
  • 您的分析器运行会告诉您有关热点的什么信息?专注于此。
  • 它被 Rabin-Miller 测试淹没了——我必须先做更多的设置。事实证明,无需设置另一个性能测试,就有一个很好的答案。
  • 好点。然而,在这里,我只是想在脑海中思考一下,是养成将变量声明为尽可能接近的习惯,还是在循环之外声明它们。很高兴知道我不必担心这里的优化。

标签: c# performance variable-declaration


【解决方案1】:

根本没有性能优势。

所有局部变量都是在创建方法的堆栈帧时分配的,因此在方法中声明它们的位置无关紧要。只是代码之间的变量范围不同,这只是编译器在编译时使用的信息。

编辑:

为了验证没有区别,我编译了两个案例并检查了生成的机器代码,两个案例是相同的:

在循环外声明变量:

            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

【讨论】:

  • 这两种情况的范围不同,所以你自相矛盾。
  • @Kon:我在哪些方面自相矛盾?
【解决方案2】:

不是真的,编译器会为你做优化。

【讨论】:

  • 这并不是真正的优化,它只是局部变量的工作方式。
猜你喜欢
  • 2023-03-18
  • 2017-06-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-31
  • 2022-11-02
  • 2014-06-15
  • 1970-01-01
相关资源
最近更新 更多