2012-02-15 7 views
7

¿Podría explicarme brevemente que comprenda esto?¿Hay alguna diferencia de rendimiento entre el uso de int a = a + 1 y a ++ en java? Si es así, ¿qué es mejor y por qué?

+4

Esto va a ser bueno. – Mob

+4

concidering micro-optimizations: siempre haga lo que sea más legible, permita que el compilador optimice para usted. El código es para programadores, las optimizaciones son para compiladores. – amit

+3

al hacer esta pregunta le costará más tiempo que la ventaja en tiempo de ejecución de la solución más rápida (si hay alguna). –

Respuesta

3

Mirando el código de bytes generada:

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; 
} 

genera (uso 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 

Así, utilizando (jdk1.6.0 _18):

x = x + 1 

crea

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

mientras que

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

todo el resultado en

iinc 

Sin embargo, hacer una prueba de rendimiento bruto en mi portátil dio lugar al lado de ninguna diferencia en el tiempo de ejecución entre los dos (a veces ++ x era más rápido, a veces x = x + 1 fue más rápido), así que no me preocuparía por las implicaciones de rendimiento.

+0

¡Y la lección que debe aprender de esto es que no puede inferir el rendimiento de Java contando códigos de byte! (Ni siquiera si ejecuta 'java -int ...' para activar la compilación de JIT). –

2

No, no habrá ninguna diferencia notable. Use lo que encuentre más legible (que es a++, normalmente).

Primera regla de optimización de código: no.

+0

downvoter: ¿me importa explicar tu voto? –

+1

No he votado negativamente, pero en realidad no estoy de acuerdo con su punto. Desde una perspectiva de código limpio 'a + = 1' es, al menos desde mi perspectiva, un enfoque más sólido tanto para la legibilidad como para la tolerancia a fallas. ¿Alguna vez evaluaste 'a +++ b' (en Java y C++)? El único argumento para a ++ fue la instrucción del procesador diferente, pero esto es ahora optimizado por JVM. – fyr

+0

no estamos discutiendo a +++ b aquí. Estamos discutiendo un ++, que es la instrucción que significa "* incrementar un *". Es legible por cualquier desarrollador de Java, y no hay ningún problema de comprensión con esta instrucción. –

0

a ++ es mucho más rápido. Se convierte en el comando INC de ensamblador. Pero creo que JVM optimizará a = a + 1, por lo que no es necesario preocuparse por eso.

0

que es lo mismo, y hoy en día con la optimización del compilador no debería estar al tanto de esas cosas, para aumentar su control del funcionamiento de otros asuntos más importantes como allocs :)

1

El compilador debe optimizar y no debe haber ninguna diferencia en absoluto. Pero hay que tener en cuenta que operador de incremento prefijo puede haber (que depende por el compilador) más rápido que el equivalente de sufijo (en C++ y C# también):

++a más rápido que a++ debido a que el operador de sufijo debe crear una variable temporal .. pensar en su aplicación:

prefijo:

a = a + 1; 
return a; 

postfix:

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

nop: http://stackoverflow.com/questions/24886/is-there-a-performance-difference-between-i-and-i-in-c – assylias

+0

como dije: ** puede ser **. no todos los compiladores optimizan de esta manera. – vulkanino

+0

@vulkanino: debe leer para usted: http://stackoverflow.com/questions/4638364/undefined-behavior-and-sequence-points-reloaded – fyr

16

En primer lugar, la Especificación del lenguaje Java no dice nada sobre el tiempo. Pero suponiendo que estamos utilizando un compilador típica como Soles javac vemos que todos los ejemplos anteriores (a++, ++a, a += 1, a = a + 1), o bien podría ser compilado en algo así como:

  • iinc instrucción, trabajando en variables:

    iload_<variable> 
    iinc <variable>, 1 
    istore_<variable> 
    
  • iadd instuction, usando la pantalla (en este caso mediante la variable 1 como el almacenamiento):

    iload_1 
    iconst_1 
    iadd 
    istore_1 
    

Depende del compilador elegir la mejor manera posible de compilarlos. P.ej. hay ninguna diferencia entre ellos. Y no debería haber ninguna diferencia entre las declaraciones, todas expresan lo mismo, sumar una a un número.

Eso beeing dijo, tanto el iinc y la versión iadd puede ser compilado usando el JIT a algo rápido y dependiente de la plataforma, y ​​al final me podría suponer que un tiempo de ejecución normal, compila las dos versiones en el mismo código ensamblador.


Con mi compilador, * * jdk1.6.0_20 los métodos de "incremento", incluso utiliza la misma instrucción.

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

     int a = 0; 

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

Este es el desmontaje:

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 

} 
+0

¿Puede usted pls. agregar detalles para '++ a' también? – Azodious

+0

@Azodious: Depende del caso, si solo agrego '++ a;' a las declaraciones anteriores, simplemente lo convertirá en otro 'iinc 1, 1'. Sin embargo, en un escenario más complejo, el orden de las instrucciones será diferente (vea esto [SO post] (http://stackoverflow.com/questions/5413548/java-prefix-postfix-of-increment-decrement-operators-need- ayuda-con-ejemplo)). – dacwe

+0

Creo que en "iinc instruction, trabajando en variables" hay un error. 'iinc' no necesita' iload' y 'istore' (?) – Johannes

Cuestiones relacionadas