una - matriz de matrices java
moderno para bucle para matriz primitiva (5)
¿Por qué no medirlo usted mismo?
Esto suena un poco duro, pero este tipo de preguntas son muy fáciles de verificar.
Simplemente cree la matriz y ejecute cada ciclo 1000 o más veces, y mida la cantidad de tiempo. Repita varias veces para eliminar problemas técnicos.
¿Hay alguna diferencia de rendimiento entre los bucles for en una matriz primitiva?
Asumir:
double[] doubleArray = new double[300000];
for (double var: doubleArray)
someComplexCalculation(var);
o:
for ( int i = 0, y = doubleArray.length; i < y; i++)
someComplexCalculation(doubleArray[i]);
Resultado de la prueba
De hecho, lo perfilé:
Total timeused for modern loop= 13269ms
Total timeused for old loop = 15370ms
Entonces, el bucle moderno realmente funciona más rápido, al menos en mi Mac OSX JVM 1.5.
Mi opinión es que no sabes y no debes adivinar. Tratar de burlar a los compiladores en estos días es infructuoso.
Hubo momentos en que la gente aprendió "Patrones" que parecían optimizar alguna operación, pero en la próxima versión de Java esos patrones fueron más lentos.
Siempre escríbelo tan claro como sea posible y no se preocupe por la optimización hasta que tenga alguna especificación de usuario en su mano y no cumpla con algún requisito, e incluso entonces tenga mucho cuidado de ejecutar pruebas antes y después para asegurarse de que su El "arreglo" realmente lo mejoró lo suficiente como para hacer que ese requisito pase.
El compilador puede hacer cosas increíbles que realmente te volarán los calcetines, e incluso si realizas una prueba que itera sobre un rango grande, puede funcionar de manera completamente diferente si tienes un rango más pequeño o cambiar lo que sucede dentro del ciclo.
Justo a tiempo la compilación significa que ocasionalmente puede superar a C, y no hay ninguna razón por la que no pueda superar el lenguaje ensamblador estático en algunos casos (el ensamblado no puede determinar de antemano que una llamada no es necesaria, Java puede hacer eso precisamente.
Para resumir: el mayor valor que puede poner en su código es escribirlo para que sea legible.
No hay diferencia. Java transformará el mejorado for en el ciclo for normal. El mejorado para solo es un "azúcar de sintaxis". El bytecode generado es el mismo para ambos bucles.
Su formulario "antiguo" escrito a mano ejecuta menos instrucciones, y puede ser más rápido, aunque tendría que perfilarlo bajo un compilador JIT determinado para estar seguro. La "nueva" forma definitivamente no es más rápida.
Si observa el código desensamblado (compilado por Sun''s JDK 1.5), verá que el formulario "nuevo" es equivalente al siguiente código:
1: double[] tmp = doubleArray;
2: for (int i = 0, y = tmp.length; i < y; i++) {
3: double var = tmp[i];
4: someComplexCalculation(var);
5: }
Entonces, puede ver que se usan más variables locales. La asignación de doubleArray
a tmp
en la línea 1 es "extra", pero no ocurre en el ciclo, y probablemente no se puede medir. La asignación a var
en la línea 3 también es extra. Si hay una diferencia en el rendimiento, esto sería responsable.
La línea 1 puede parecer innecesaria, pero es una repetición del resultado si la matriz se calcula con un método antes de ingresar al ciclo.
Dicho esto, usaría el nuevo formulario, a menos que necesite hacer algo con la variable de índice. Es probable que el compilador JIT optimice cualquier diferencia de rendimiento en el tiempo de ejecución, y la nueva forma es más clara. Si continúa haciéndolo "a mano", puede perder optimizaciones futuras. En general, un buen compilador puede optimizar bien el código "estúpido", pero tropieza con el código "inteligente".
Tengo mucha curiosidad sobre tu pregunta, incluso después de mi respuesta anterior. Así que decidí verificarlo yo también. Escribí este pequeño fragmento de código (ignore la corrección matemática para verificar si un número es primordial ;-)):
public class TestEnhancedFor {
public static void main(String args[]){
new TestEnhancedFor();
}
public TestEnhancedFor(){
int numberOfItems = 100000;
double[] items = getArrayOfItems(numberOfItems);
int repetitions = 0;
long start, end;
do {
start = System.currentTimeMillis();
doNormalFor(items);
end = System.currentTimeMillis();
System.out.printf("Normal For. Repetition %d: %d/n",
repetitions, end-start);
start = System.currentTimeMillis();
doEnhancedFor(items);
end = System.currentTimeMillis();
System.out.printf("Enhanced For. Repetition %d: %d/n/n",
repetitions, end-start);
} while (++repetitions < 5);
}
private double[] getArrayOfItems(int numberOfItems){
double[] items = new double[numberOfItems];
for (int i=0; i < numberOfItems; i++)
items[i] = i;
return items;
}
private void doSomeComplexCalculation(double item){
// check if item is prime number
for (int i = 3; i < item / 2; i+=2){
if ((item / i) == (int) (item / i)) break;
}
}
private void doNormalFor(double[] items){
for (int i = 0; i < items.length; i++)
doSomeComplexCalculation(items[i]);
}
private void doEnhancedFor(double[] items){
for (double item : items)
doSomeComplexCalculation(item);
}
}
Al ejecutar la aplicación, obtuve los siguientes resultados para mí:
Normal para. Repetición 0: 5594 Mejorado para. Repetición 0: 5594
Normal para. Repetición 1: 5531 Mejorado para. Repetición 1: 5547
Normal para. Repetición 2: 5532 Mejorado para. Repetición 2: 5578
Normal para. Repetición 3: 5531 Mejorado para. Repetición 3: 5531
Normal para. Repetición 4: 5547 Mejorado para. Repetición 4: 5532
Como podemos ver, la variación entre los resultados es muy pequeña, y algunas veces el ciclo normal se ejecuta más rápido, a veces el ciclo mejorado es más rápido. Como hay otras aplicaciones abiertas en mi computadora, me parece normal. Además, solo la primera ejecución es más lenta que las demás; creo que esto tiene que ver con las optimizaciones de JIT.
Los tiempos promedio (excluyendo la primera repetición) son 5535,25 ms para el ciclo normal y 5547 ms para el ciclo mejorado. Pero podemos ver que los mejores tiempos de ejecución para ambos bucles son los mismos (5531 ms), así que creo que podemos llegar a la conclusión de que ambos bucles tienen el mismo rendimiento, y las variaciones de tiempo transcurren debido a otras aplicaciones (incluso el sistema operativo) de la máquina.