在for循环中声明的变量是否会影响循环的性能?

tet*_*sun 10 c# for-loop variable-declaration

我已经完成了我的作业,并且一再保证,无论是在for循环内部还是外部声明变量,它在性能上都没有区别,它实际上编译为完全相同的MSIL.但是我一直在弄乱它,并发现在循环中移动变量声明确实会导致相当大的一致性能增益.

我编写了一个小型控制台测试类来测量这种效果.我初始化一个静态double[]数组项,两个方法对它执行循环操作,将结果写入静态double[]数组缓冲区.最初,我的方法是那些我注意到差异的方法,即复数的大小计算.对于长度为1000000 的项目数组运行这些100次,我得到的变量(6个double变量)在循环内的运行时间一直较低:例如,32,83±0,64 ms v 43,44±使用Intel Core 2 Duo @ 2.66 GHz的老式配置为0.45 ms.我尝试以不同的顺序执行它们,但它没有影响结果.

然后我意识到计算复数的大小远非最小的工作示例,并测试了两个更简单的方法:

    static void Square1()
    {
        double x;

        for (int i = 0; i < buffer.Length; i++) {
            x = items[i];
            buffer[i] = x * x;
        }
    }


    static void Square2()
    {
        for (int i = 0; i < buffer.Length; i++) {
            double x;
            x = items[i];
            buffer[i] = x * x;
        }
    }
Run Code Online (Sandbox Code Playgroud)

有了这些,结果就出现了另一种方式:在循环外声明变量似乎更有利:对于Square1()v 12.07±0.51 ms,声明为7.07±0.43 ms Square2().

我不熟悉ILDASM,但我已经拆解了这两种方法,唯一的区别似乎是局部变量的初始化:

      .locals init ([0] float64 x,
       [1] int32 i,
       [2] bool CS$4$0000)
Run Code Online (Sandbox Code Playgroud)

Square1()

      .locals init ([0] int32 i,
       [1] float64 x,
       [2] bool CS$4$0000)
Run Code Online (Sandbox Code Playgroud)

Square2().根据它,stloc.1一个是stloc.0在另一个中,反之亦然.在较长的复杂幅度计算中,MSIL代码甚至代码大小也不同,我stloc.s i在外部声明代码中看到stloc.0了内部声明代码中的内容.

那怎么可能呢?我忽略了什么或者它是真正的效果吗?如果是,它可以在长循环的性能上产生显着差异,所以我认为值得讨论.

非常感谢您的想法.

编辑:我忽略的一件事是在发布之前在几台计算机上测试它.我现在在i5上运行它,两种方法结果几乎相同.对于发布这种误导性的观察我表示歉意.

Bat*_*eba 5

任何值得盐的C#编译器都会为你执行这样的微优化.如果必要,仅在范围外泄漏变量.

因此double x;,如果可能,请保持循环内部.

就个人而言,如果items[i]是普通的数据阵列访问,那么我会写buffer[i] = items[i] * items[i];.C和C++会对此进行优化,但我不认为C#会(但); 你的反汇编暗示它没有.