【问题标题】:Performance difference between using int a=a+1 and a++ in Java在 Java 中使用 int a=a+1 和 a++ 之间的性能差异
【发布时间】:2012-03-06 17:39:21
【问题描述】:

Java 中使用int a=a+1a++ 有性能差异吗?

如果是这样,哪个更好,为什么?您能否简要解释一下以使我理解这一点?

【问题讨论】:

  • 考虑微优化:总是做更具可读性的事情,让编译器为你优化。代码是给程序员的,优化是给编译器的。
  • 问这个问题比更快(如果有的话)解决方案的运行时间优势要花费你更多的时间。
  • @Bernhard:我只是想知道有没有区别

标签: java performance post-increment


【解决方案1】:

首先,Java 语言规范没有说明时间。但假设我们使用的是典型的编译器,例如 Suns javac,我们会看到上述所有示例(a++++aa += 1a = a + 1)都可以编译成类似的内容:

  • iinc 指令,处理变量:

    iload_<variable>
    iinc <variable>, 1
    istore_<variable>
    
  • iadd指令,使用栈(这里使用变量1作为存储):

    iload_1
    iconst_1
    iadd
    istore_1
    

由编译器选择最好的编译方式。例如。它们之间没有区别。语句之间不应该有任何区别 - 它们都表达相同的东西 - 将数字加一。

也就是说,iinciadd 版本都可以使用 JIT 编译为快速且依赖于平台的东西,最后我假设正常的运行时会将两个版本编译成相同的汇编代码.


使用我的编译器,*jdk1.6.0_20*“增量”方法甚至使用相同的指令。

public class Test {
    public static void main(String[] args) {

        int a = 0;

        a = a + 1;
        a += 1;
        a++;
        ++a;
    }
}

这是反汇编:

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

public static void main(java.lang.String[]);
  Code:
   0:   iconst_0
   1:   istore_1
   2:   iinc    1, 1   // a = a + 1;
   5:   iinc    1, 1   // a += 1;
   8:   iinc    1, 1   // a++;
   11:  iinc    1, 1   // ++a;
   14:  return

}

【讨论】:

  • 你能请。还要添加++a 的详细信息吗?
  • @Azodious:视情况而定,如果我只是在上述语句中添加++a;,它只会将其转换为另一个iinc 1, 1。然而,在更复杂的场景中,指令的顺序会有所不同(参见SO post)。
  • 我认为在“iinc 指令,处理变量”中存在错误。 iinc 不需要 iloadistore (?)
【解决方案2】:

查看生成的字节码:

public static void main(String[] args) {
    int x = 1;
    int y = 1;
    int z = 1;
    int a = 1;
    int b = 1;
    x = x + 1;
    y++;
    ++z;
    a += 1;
    b += 2;
}

生成(使用javap -c classname

0:   iconst_1
1:   istore_1
2:   iconst_1
3:   istore_2
4:   iconst_1
5:   istore_3
6:   iconst_1
7:   istore  4
9:   iconst_1
10:  istore  5
12:  iload_1
13:  iconst_1
14:  iadd
15:  istore_1
16:  iinc    2, 1
19:  iinc    3, 1
22:  iinc    4, 1
25:  iinc    5, 2
28:  return

所以使用(jdk1.6.0_18):

x = x + 1

创造

12:  iload_1
13:  iconst_1
14:  iadd
15:  istore_1

y++;
++z;
a += 1;

所有结果

iinc

但是,在我的笔记本电脑上进行粗略的性能测试导致两者之间的运行时间几乎没有差异(有时 ++x 更快,有时 x=x+1 更快),所以我不会担心性能影响。

【讨论】:

  • 您应该从中吸取的教训是,您不能通过计算字节码来推断 Java 性能! (即使您使用 java -int ... 运行以关闭 JIT 编译也不会。)
【解决方案3】:

不,不会有任何明显的差异。使用您认为最易读的内容(通常是a++)。

代码优化的第一条规则:不要。

【讨论】:

  • 我没有投反对票,但实际上我不同意你的观点。从干净代码的角度来看,a+=1 至少从我的角度来看是一种更可靠的可读性和容错方法。您是否评估过a+++b(在Java 和C++ 中)? a++ 的唯一论据是不同的处理器指令,但如今已由 JVM 优化。
  • 我们这里不讨论 a+++b。我们正在讨论 a++,它是指令,意思是“increment a”。任何 Java 开发人员都可以阅读它,并且该指令不存在可理解性问题。
  • 这正是每个人都应该理解的重点。但这并不是说“增加a”。 a++的意思是“在当前表达式之后增加a”
  • 不是当使用的表达式只是a++。在这种情况下,增量是在赋值之前还是之后完成都没有关系:没有赋值。那是 OP 的问题:a = a + 1a++?
【解决方案4】:

编译器应该优化,应该没有区别。 但请记住,前缀递增运算符 可能是(取决于编译器)比后缀等效(在 C++ 和 C# 中)更快:

++aa++ 快​​,因为后缀运算符必须创建一个临时变量.. 想想它们的实现:

前缀:

a = a + 1;
return a;

后缀:

int tmp = a;
a = a + 1;
return tmp;

【讨论】:

【解决方案5】:

a++ 更快。它转换为汇编程序的 INC 命令。但我认为 JVM 会优化 a=a+1 所以你不需要关心。

【讨论】:

    【解决方案6】:

    也是一样,现在编译器优化不应该意识到这些东西,以提高你的性能检查其他更大的问题,如 allocs :)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-05-02
      • 2017-12-11
      • 2021-10-07
      • 2019-11-07
      • 1970-01-01
      • 1970-01-01
      • 2016-04-14
      相关资源
      最近更新 更多