EDICIóN GENERAL

¿Por qué es 2 * (i * i) más rápido que 2 * i * i en Java? (Eng)

Basicamente porque multiplicar por 2 es extremadamente fácil y cuanto más grande sea el número a multiplicar por 2 más tiempo ahorrará.
Supongamos que multiplicar x2 es un 10% más rápido que multiplicar por cualquier otro número.
La multiplicación tiene un coste (hay bastantes mov, push cambios de registro etc...)
Si yo multiplico 2x500x500 primero hago 2x500=1000 y luego 1000*500 Nos queda que el numéro más grande no se ultiplica por dos
En cambio si yo multiplico (500x500) tengo 250000 y luego lo multiplico por 2 por lo que la operación más costosa la hago con el multiplicador más fácil para la máquina.
#30 Salvo que te estés saliendo de rango y necesites un tipo más gordo, cuesta el mismo tiempo/recursos multiplicar 2x2 que 2.000.000x2.000.000. Los circuitos no funcionan así.
#55 Cuando multiplicas por 2 solo haces 1 mov ;)

1 --> 1 * 2 --> 10
2 --> 10 *2 --> 100
3--> 11 * 2 --> 110
4-->100 *2 --> 1000
#58 Sí, multiplicar por dos se resuelve con un desplazamiento, pero en este caso esa no puede ser la solución, ya que, con paréntesis o sin ellos, tienes que hacer las mismas operaciones: un desplazamiento y una multiplicación. Y la multiplicación tarda lo mismo, sea con números grandes o pequeños.

Al final, la respuesta está en el propio enlace: simplemente el optimizador de código es mierder y en un caso no optimiza lo suficiente. Probablemente en alguna versión posterior lo mejoren, y se resolverá el tema.
#58 #55 Y si no recuerdo mal la instrucción era shl o algo así, la que no rota (hace muchos años ya que hice ensamblador en ingeniería informática).
#64 shl (shift left) desplaza a la izquierda y por tanto multiplica por dos, y shr desplaza a la derecha y divide por dos. Puedes multiplicar dividir por una potencia de 2 (2, 4, 8...) a coste casi cero. En cambio, multiplicar son unos cuantos ciclos.

Obviamente el tema sólo vale para enteros, para floats y compañía no cuela el truqui.
#55 No tiene por qué costar el mismo tiempo. Dependerá de la capacidad de representación de números que tenga tu procesador, de la memoria que tenga... etc... No todos los circuitos funcionan igual.... ni todos los procesadores calculan mediante los mismos algoritmos...
#84 Ya he dicho que si te sales del rango la cosa puede cambiar, pero aquí hablamos de un int que, en Java, es un mundano número entero de 32 bits. Dos multiplicaciones de dos números de 32 bits tardan exactamente lo mismo, independientemente del valor, en cualquier procesador desde el 386 hasta un Core i9.

Otra cosa es que hablemos de números muy tochos, en plan BigInteger y tal, que ya son objetos y la cosa puede depender de la implementación. Pero con tipos básicos no hay diferencia, al circuito le da igual si de esos 32 bits usas todos o sólo unos pocos. Él multiplica todos igual, en paralelo.
#30 El problema no viene por ahi. Estoy convencido que estoy pasa tambien si en vez de multiplicar por dos multiplicadas por tres. Internamente, la JVM esta pensada como una maquina de pila, no de registros. Cuando conviertes ese código a código nativo, acabas generando código que utiliza una cantidad muy pequeña de registros.

Muy por encima (en pseudoensamblador), imagino que la opción rápida hace:
MOV RAX [i]
MUL RAX, RAX, RAX
MUL RAX, RAX, 2

Mientras que la opción lenta hace:
MOV RAX, [i]
MUL RAX, RAX, 2
MOV RBX, [i]
MUL RAX, RAX, RBX

En el primer caso, se esta haciendo una única llamada a [i] (traer el valor de i desde memoria), mientras que en el segundo, se trae el valor de [i] dos veces. Incluso si en el segundo fragmento juegas un poco con el orden:
MOV RBX [i]
MUL RAX, RBX, 2
MUL RAX, RAX, RBX

Aunque ahora solo usas una llamada a [i], sigues utilizando dos registros. Lo que significa que tienes que guardar el contenido de dichos registros antes en la pila, lo cual también te lleva tiempo.

No me he puesto a mirar en serio la verdad, pero por lo que me conozco de la JVM (basicamente mi trabajo), apostaria dinero a que viene por ahi
#123 No se porque pero me ha recordado a Mars Attack!!!

menéame