Есть ли разница в производительности между использованием int a = a + 1 и a ++ в java?Если так, что лучше и почему? - PullRequest
7 голосов
/ 15 февраля 2012

Не могли бы вы кратко объяснить мне, чтобы понять это?

Ответы [ 6 ]

16 голосов
/ 15 февраля 2012

Прежде всего, спецификация языка Java ничего не говорит о времени. Но предполагая, что мы используем типичный компилятор, такой как Suns javac, мы видим, что все приведенные выше примеры (a++, ++a, a += 1, a = a + 1) могут быть скомпилированы в нечто вроде:

  • iinc инструкция, работающая с переменными:

    iload_<variable>
    iinc <variable>, 1
    istore_<variable>
    
  • iadd, используя стек (здесь используется переменная 1 в качестве хранилища):

    iload_1
    iconst_1
    iadd
    istore_1
    

Компилятор должен выбрать наилучший из возможных способов их компиляции. Например. между ними нет разницы . И не должно быть никакой разницы между утверждениями - все они выражают одно и то же - добавляя один к числу.

В связи с этим версия iinc и iadd может быть скомпилирована с использованием 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

}
3 голосов
/ 15 февраля 2012

Глядя на сгенерированный байт-код:

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 был быстрее), поэтому я не стал бы беспокоиться о влиянии на производительность.

2 голосов
/ 15 февраля 2012

Нет, заметной разницы не будет.Используйте то, что вы считаете наиболее читабельным (обычно a++).

Первое правило оптимизации кода: не.

1 голос
/ 15 февраля 2012

Компилятор должен оптимизировать и не должно быть никакой разницы. Но имейте в виду, что оператор приращения префикса может быть (зависит от компилятора) быстрее, чем эквивалент постфикса (также в C ++ и C #):

++a быстрее, чем a++, потому что оператор постфикса должен создать временную переменную. Подумайте об их реализации:

префикс:

a = a + 1;
return a;

постфикс:

int tmp = a;
a = a + 1;
return tmp;
0 голосов
/ 15 февраля 2012

Это то же самое, и в настоящее время с оптимизацией компилятора не следует знать об этом, чтобы увеличить производительность, проверьте другие большие проблемы, такие как allocs:)

0 голосов
/ 15 февраля 2012

а ++ намного быстрее.Он преобразуется в команду INC на ассемблере. Но я думаю, что JVM оптимизирует a = a + 1, поэтому вам не нужно об этом заботиться.

...