2011-01-28 12 views
29

en Java Normalmente suelo hacer un bucle para como siguiente:¿Es ++ realmente más rápido que i ++ en for-loops en java?

for (int i = 0; i < max; i++) { 
    something 
} 

Sin embargo, recientemente un colega mecanografié manera:

for (int i = 0; i < max; ++i) { 
    something 
} 

Dijo que el último sería más rápido. ¿Es eso cierto?

+6

Creo que tendrá problemas para medir la diferencia actual. Por lo general, se obtienen mejores resultados optimizando la parte * dentro * del bucle;) –

+2

Podría ser, pero tan poco que nunca lo notarías. Las micro optimizaciones como esta son totalmente inútiles. –

+1

@PeeHaa: Ambos bucles ejecutan la misma cantidad de ciclos. Intenté con max = 10 y ambos van de 0 a 9 para i. – Mnementh

Respuesta

53

No, no es cierto. Puede medir el rendimiento al sincronizar cada ciclo para una gran cantidad de iteraciones, pero estoy bastante seguro de que serán las mismas.

El mito vino de C donde ++i se consideró más rápido que i++ porque el primero se puede implementar aumentando y luego devolviéndolo. Esto último podría implementarse copiando el valor de i en una variable temporal, incrementando i, y luego devolviendo el valor temporal. La primera versión no necesita hacer la copia temporal y muchas personas suponen que es más rápida. Sin embargo, si la expresión se utiliza como una declaración, los compiladores de C modernos pueden optimizar la copia temporal de manera que no haya diferencia en la práctica.

+0

Gracias por la gran explicación. – Binabik

+12

Los compiladores modernos optimizarán esto, pero si está usando C++, yi es un objeto (por ejemplo, un interador), y esos operadores no están en línea, ++ seré más rápido que i ++. – fbafelipe

+0

Además, si va a una entrevista de trabajo, debe decir que es más rápido :) Pero si comienza a usar iteradores en C++, no existe tal cosa como ++.Y seguirás golpeando tu cabeza contra la pared por recibir los mismos estúpidos mensajes de error una y otra vez. Como yo x) –

5

Incluso si lo es, lo cual dudo mucho, su colega realmente debería tener mejores cosas para pasar el tiempo aprendiendo que cómo optimizar una expresión de bucle.

+14

Mirar, ¡mamá! ¡Mi programa se ejecuta más rápido si solo uso letras de la primera mitad del alfabeto para nombres de variables! Para la máquina de refactorización! –

+1

@Rafe Kettler Sería aterrador si fuera verdad. :) – biziclop

+2

lo que da miedo es que en muchos compiladores, los nombres de variables más cortos usan menos memoria. Podríamos obsesionarnos todo el día con los pequeños hacks, pero mi procesador no tiene 730 millones de transistores sin ningún motivo. –

9

Para cualquier optimizador razonablemente capaz, serán exactamente iguales. Si no está seguro, mire el bytecode de salida o perfíllo.

1

No será más rápido. El compilador y la JVM con el JIT harán picadillo de tan insignificantes diferencias.

Puede utilizar las técnicas habituales de optimización de bucle para obtener ventajas de velocidad, como desenrollar, si corresponde.

-2

Incluso uno sería más rápido, a nadie le importa en los días de HotSpot. Lo primero que hace el JIT es eliminar todas las optimizaciones que hizo javac. Después de eso, todo queda en el JIT para hacerlo rápido.

+5

[citación necesitada] para HotSpot eliminar todas las optimizaciones javac – Malfist

+2

optimizaciones consisten en eliminar o reestructurar cosas, por lo que no hay nada que "eliminar". – scravy

0

En Java no debería haber ninguna diferencia - cualquier compilador moderno * debería generar el mismo código de bytes (sólo una iinc) en ambos casos, ya que el resultado de la expresión de la subasta no se utiliza directamente .
hay una tercera opción, sigue siendo el mismo código de bytes *:

for (int i = 0; i < max; i += 1) { 
    something 
} 

*probado con el compilador de Eclipse

1

No habrá ninguna diferencia en absoluto.

Esto vino de C++ pero incluso allí no habría ninguna diferencia en este caso. Donde hay una diferencia es donde yo soy un objeto. i ++ tendría que hacer una copia adicional del objeto, ya que tiene que devolver el valor original sin modificar del elemento, mientras que ++ puede devolver el objeto modificado para que guarde una copia.

En C++ con el objeto definido por el usuario, el costo de una copia puede ser significativo, por lo que vale la pena recordarlo.Y debido a esto, la gente tiende a usarlo también para variables int, ya que de todos modos es igual de bueno ...

1

Descompila con "javap -c YourClassName" y observa el resultado y decide a partir de eso. De esta forma, verá lo que el compilador realmente hace en cada caso, no lo que cree que hace. De esta forma, también verá POR QUÉ una forma es más rápida que la otra.

34

Esta pregunta necesita un código de bytes de Java. Considere el siguiente código:

public class PostPre { 
    public static void main(String args[]) { 
     int n = 5; 
     loop1(n); 
     loop2(n); 
    } 

    public static void loop1(int n) { 
     for (int i = 0; i < n; i++) {} 
    } 

    public static void loop2(int n) { 
     for (int i = 0; i < n; ++i) {} 
    } 
} 

Ahora compila y desmontarlo:

$ javac PostPre.java; javap -c PostPre.class 
Compiled from "PostPre.java" 
public class PostPre { 
    public PostPre(); 
    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_5  
     1: istore_1  
     2: iload_1  
     3: invokestatic #2     // Method loop1:(I)V 
     6: iload_1  
     7: invokestatic #3     // Method loop2:(I)V 
     10: return   

    public static void loop1(int); 
    Code: 
     0: iconst_0  
     1: istore_1  
     2: iload_1  
     3: iload_0  
     4: if_icmpge  13 
     7: iinc   1, 1 
     10: goto   2 
     13: return   

    public static void loop2(int); 
    Code: 
     0: iconst_0  
     1: istore_1  
     2: iload_1  
     3: iload_0  
     4: if_icmpge  13 
     7: iinc   1, 1 
     10: goto   2 
     13: return   
} 

loop1() y loop2() tienen el mismo código de bytes.

2

Prueba esto en su entorno

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

     long foo; //make sure the value of i is used inside the loop 
     long now = 0; 
     long prefix = 0; 
     long postfix = 0; 

     for (;;) { 
      foo = 0; 
      now = System.currentTimeMillis(); 
      for (int i = 0; i < 1000000000; i++) { 
       foo += i; 
      } 
      postfix = System.currentTimeMillis() - now; 

      foo = 0; 
      now = System.currentTimeMillis(); 
      for (int i = 0; i < 1000000000; ++i) { 
       foo += i; 
      } 
      prefix = System.currentTimeMillis() - now; 

      System.out.println("i++ " + postfix + " ++i " + prefix + " foo " + foo); 
     } 
    } 
} 

El mío me da

i++ 1690 ++i 1610 foo 499999999500000000 
i++ 1701 ++i 1610 foo 499999999500000000 
i++ 1701 ++i 1600 foo 499999999500000000 
i++ 1701 ++i 1610 foo 499999999500000000 
i++ 1701 ++i 1611 foo 499999999500000000 
i++ 1701 ++i 1610 foo 499999999500000000 
i++ 1691 ++i 1610 foo 499999999500000000 
i++ 1701 ++i 1600 foo 499999999500000000 
i++ 1701 ++i 1610 foo 499999999500000000 
i++ 1691 ++i 1610 foo 499999999500000000 
i++ 1701 ++i 1610 foo 499999999500000000 
i++ 1691 ++i 1610 foo 499999999500000000 
i++ 1701 ++i 1610 foo 499999999500000000 
i++ 1701 ++i 1610 foo 499999999500000000 
i++ 1701 ++i 1610 foo 499999999500000000 
i++ 1692 ++i 1610 foo 499999999500000000 
i++ 1701 ++i 1610 foo 499999999500000000 
i++ 1691 ++i 1610 foo 499999999500000000 

Así que incluso si no es que mucho, me Asume que hay una diferencia

0

En Java no existe tal diferencia El código interpertes de la máquina Java y no importa si escribe ++ i o i ++, se convertirá en código de bytes para exactamente el mismo conjunto de instrucciones.

Pero en C/C++ hay una gran diferencia y si no está utilizando ninguna marca de optimización, entonces su ciclo puede ser más lento hasta 3 veces.

El uso de indicadores de optimización como -O/-O3 obligará al compilador a simplificar el código de ensamblaje de salida (en la mayoría de los casos) y, por lo tanto, a hacerlo más rápido (en la mayoría de los casos).

Cuestiones relacionadas