每个范围初始化一个循环迭代器是否更好?

时间:2016-03-03 06:36:19

标签: java for-loop optimization initialization

我认为问题应该是自我解释的,我现在正在考虑的语言是Java,但它可能适用于所有语言。

话虽如此,基本上我所说的是这个:

// Initialize first
int i = 0;

for (i = 0; i < x; i++) {
    // do some stuff
}

for (i = 0; i < x; i++) {
    // do some more stuff
}

for (i = 0; i < x; i++)  {
    // do other stuff
}

比这更好:

// Initializing i in the for loop

for(int i = 0; i < x; i++) {
    // do some stuff
}

for(int i = 0; i < x; i++) {
    // do some more stuff
}

for(int i = 0; i < x; i++) {
    // do other stuff
}

这是一个性能问题,我正在谈论初始化一次/每个/范围的解决方案。

4 个答案:

答案 0 :(得分:2)

我使用x=10执行了性能测试,以评估循环内声明方法和循环外声明方法之间的性能差异。

详细信息:我首先使用in-loop运行代码300x,然后首先使用out-loop运行300x代码。每次运行,我都以纳秒记录总运行时间,以执行10,000次方法。所以,我总共记录了1200次观察(每种方法600次)。为了测量稳态性能(副启动性能),我从每个持续时间最长的数据集中删除了20个观测值。 (20次启动观测的平均运行时间比所有其他观测值的平均运行时间大一个数量级。)

结果:单因素ANOVA表明循环内声明比循环外声明(p-value=8.12584E-07)更快。对于环内,平均运行时间为158635.4931纳秒,对于环外,平均运行时间为166943.7397纳秒。从实际的角度来看,我们谈论的是每10,000次迭代的差异为~0.01ms。

结论: 只需使用循环声明。 @FallAndLearn还指出循环声明更容易维护,因为局部变量{{1}声明的范围尽可能小。

答案 1 :(得分:0)

local variables的范围应始终为最小

因此,如果在循环外没有使用int i,那么第二种方式总是更好。更具可读性。

Performance明智的他们都是same。从maintenance的角度来看,第二种选择更好。

此外,这个问题的答案将取决于您的要求。如果您的代码具有依赖于i的其他数据或只有三个for循环语句。

答案 2 :(得分:0)

你的第一段代码比第二段更好,因为int是一个值类型,一旦你初始化它就将它的值存储在堆栈中,稍后你只需要一次又一次地为该类型赋值。 另一方面(第二段代码),您正在初始化我三次,即创建三次堆栈条目。 所以第一段代码比第二段更好,性能明智。

答案 3 :(得分:0)

让我们查看以下代码段的反汇编代码:

DECLARE @x XML = '
<Customize xmlns="http://utsavfashion.com/web/schemas">   
    <customize_details> 
        <entityid>876</entityid>    
    </customize_details>
</Customize>'

DECLARE @doc INT, @xmlns VARCHAR(100)

SET @xmlns = '<root xmlns:h="http://utsavfashion.com/web/schemas" />'
EXEC sp_xml_preparedocument @doc OUTPUT, @x, @xmlns

SELECT *
FROM OPENXML(@doc, '//h:Customize/h:customize_details')
    WITH (
        entityid INT '.'
    )

EXEC sp_xml_removedocument @doc
public class Test {
    public static void main(String[] args) {
        int i = 0;
        for(i = 0; i < 3; i++){
            //do some stuff
        }
    }
}

现在让我们为循环中的控制变量初始化生成另一个:

public class Test {
  public Test();
    Code:
       0: aload_0
       1: invokespecial #1    // Method java/lang/Object."<init>":()V
       4: return

  public static void main(java.lang.String[]);
    Code:
       0: iconst_0
       1: istore_1
       2: iconst_0
       3: istore_1
       4: iload_1
       5: iconst_3
       6: if_icmpge     15
       9: iinc          1, 1
      12: goto          4
      15: return
}

他们相同,我不是字节码专家,但我可以说第二个开销较少。第一个将public class Test { public Test(); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return public static void main(java.lang.String[]); Code: 0: iconst_0 1: istore_1 2: iload_1 3: iconst_3 4: if_icmpge 13 7: iinc 1, 1 10: goto 2 13: return } 常量推迟两次(两个int指令),并且与第二个代码中的一条指令相比,有两条iconst_<i>指令。