2012-01-20 617 views
6

¿El compilador de Java optimizar las operaciones matemáticas sencillas, como repetida:¿El compilador optimizará los cálculos matemáticos repetidos?

if (prevX/width != curX/width) { 
    // Do something with prevX/width value 
} else { 
    // Do something with curX/width value 
} 

Sé que sólo puede asignar los resultados a una variables antes de la sentencia if, y devolver las variables, pero es tipo de engorroso. Si el compilador reconoce automáticamente que se están haciendo los mismos cálculos y almacena en caché los resultados en variables temporales por sí mismo, prefiero apegarme a la convención anterior.

* Editar - Soy un idiota. Intenté simplemente/resumir mi pregunta demasiado. No es tan simple como: if (x> y)

+1

a menos que el ancho sea negativo, ¿no puede ir 'if (x> y) ...' – user949300

+1

¿Por qué no simplemente 'Math.max (x/width, y/width)'? También @ user949300: si estos son enteros, podría dar un resultado diferente. –

+0

@Eric Andres No creo que las entradas importen en el problema original presentado, ya que solo fue una verificación de 2 vías (no verificó la igualdad) Si (x> y), no hay manera de que x/ancho es 0. Pero los importes importarían mucho en la nueva pregunta, entonces +1 a usted. – user949300

Respuesta

7

La respuesta es sí. Esto se llama Common Subexpression Elimination y es una optimización de compilador estándar (y potente) utilizada en Java, C/C++ y otros ...

This page confirma que la HotSpot JVM hará esta optimización.


Dicho esto, si el compilador/tiempo de ejecución será capaz de hacer esta optimización cuando se espera que a es otra historia. Por lo tanto, prefiero hacer estas optimizaciones si también mejora la legibilidad.

double xw = x/width; 
double yw = y/width; 

if (xw > yw) { 
    return xw; 
} else { 
    return yw; 
} 
+1

+1: el compilador 'javac' no tiene optimizaciones, sin embargo, es muy probable que el compilador nativo JIT lo haga suponiendo que compila el código (la mayoría de los códigos no se compilan en nativos) porque no se ejecuta lo suficiente) –

2

En general, "sí": el compilador optimizará el código si es posible, y el HotSpot JVM también puede mejorar los bloques de código ejecutados repetidamente.

En este caso, sin embargo, que sería mejor refactorizar el código como el siguiente:

if (x > y) 
    return x/width; 
return y/width; 

que evita el funcionamiento de una división si x > y.

+0

Solo quiero agregar que depender de las optimizaciones del compilador y otras características no documentadas no es una buena práctica de programación. Si los resultados son los mismos o no, escribir un código eficiente siempre mejora la calidad del código. – buc

+0

@buc ​​99% del código que escribe no es sensible al rendimiento y la mayoría de las veces el código más eficiente no es el más fácil de mantener. Especialmente con cuán buenos son los compiladores en estos días para preocuparse de si harán CSE en una función matemática simple, como esto es inútil. Simplemente escriba el código más claro ... – Voo

3

El compilador puede realizar dichas optimizaciones. Ya sea que realmente hace depende de las respuestas a las siguientes:

es el compilador permitido hacer esto por el JLS?

En algunos casos no lo es. Por ejemplo, si prevX era una variable de instancia volatile, debe recuperarse de la memoria cada vez que el código fuente dice que se utiliza. Otro caso es donde la subexpresión común implica una llamada al método con un efecto secundario observable; es decir, donde algo más en el programa podría ser capaz de decir si el método se llama una o dos veces.

¿Es capaz el compilador de de hacerlo?

Un compilador necesita analizar el código para detectar subexpresiones comunes que podrían ser legalmente optimizadas. Hay dos problemas aquí:

  • ¿El compilador es capaz de realizar el razonamiento necesario? Por ejemplo, uno podría hipotetizar un compilador que puede determinar que una llamada a un método específico será libre de efectos secundarios y que, por lo tanto, puede optimizarse. Sin embargo, construir un compilador que realmente sea capaz de hacer esto es ...y un problema interesante

  • ¿La optimización vale la pena? Existe una compensación entre el costo de realizar una optimización y los beneficios. No es una solución directa. Debe tener en cuenta el costo de mirar para ver si se puede realizar una optimización ... cuando en realidad no se puede. En otras palabras, el impacto en el tiempo de compilación. (Oso y cuenta que en Java las optimizaciones se hacen sobre todo en tiempo de ejecución por el compilador JIT ... así que esto repercute en el rendimiento de la aplicación.)

En un ejemplo sencillo como la suya, la optimización es legal (módulo volatile) y uno debería esperar un compilador JIT medio decente para realizarlo.


La otra pregunta es si usted debe tratar de ayuda al compilador mediante la evaluación de las expresiones comunes de forma explícita su código y la asignación de los resultados a los temporales.

IMO, la respuesta es generalmente no.

  • Un buen compilador probablemente funcionará tan bien como usted en esto. Y si no lo hace, entonces la próxima generación puede hacer.

  • El código probablemente no garantiza la optimización manual. A menos que hayas perfilado tu código para determinar dónde están los cuellos de botella, tus optimizaciones de mano tienen una buena probabilidad de ser irrelevante para el rendimiento real de la aplicación ... y una pérdida de tiempo.

  • Existe la posibilidad de que lo rellene; p.ej. por olvidando que una llamada a un método tiene un efecto secundario importante o que una variable es volatile por una buena razón.

Por otro lado, si la reescritura hace que el código sea más legible , esa es una buena razón para hacerlo.

+0

+1 para una respuesta detallada. – Mysticial

Cuestiones relacionadas