2009-07-21 6 views
34

En C++ puedo declarar un método "en línea" y es probable que el compilador lo alinee. Por lo que yo entiendo, no hay tal palabra clave en Java.Inlineación en Java

¿La alineación se realiza si la JVM decide hacerlo? ¿Puedo influir en esta decisión de alguna manera?

Respuesta

49

Un par de las otras respuestas han sugerido que sólo los métodos finales pueden ser inline - esto no es cierto, como HotSpot es lo suficientemente inteligente como para ser capaz de inline métodos no final, siempre y cuando no se han anulado aún. Cuando se carga una clase que anula el método, puede deshacer su optimización. Obviamente, hacer que el método sea el último significa que nunca se requiere ...

Básicamente deje que la JVM haga su trabajo; es probable que sea mucho mejor para determinar dónde en línea que usted.

¿Tiene una situación en la que está convencido de que la JVM no está haciendo un buen trabajo?Suponiendo que está utilizando HotSpot, ¿ha intentado utilizar la versión del servidor en lugar del cliente? Eso puede hacer una gran diferencia .

+28

En realidad, HotSpot puede alinear métodos (especulativamente) incluso si se reemplaza, y llamar al método virtualmente para objetos que no son del tipo esperado. Server HotSpot incluso incluirá dos versiones diferentes de un método (en línea bimorfa). –

+2

@Tom: ¿Te importaría incluir eso en la respuesta? –

+3

Bueno, definitivamente tuve casos donde el hotspot no estaba en línea y la incorporación manual condujo a una mejora del factor 5 en el rendimiento de un ciclo de procesamiento central. –

4

Inlining es más probable que ocurra si el método en cuestión es:

  • corta
  • última
  • no depende de algún método final de duración, sin

ya que son las solo circunstancias donde la JVM puede estar segura de los efectos de la llamada.

+1

'final' no hace ninguna diferencia para HotSpot. –

+0

@ TomHawtin-tackline Interesante, ¿podría dar más detalles? –

+0

@MCEmperor Sujeto a cambios, pero solo comprobó si las clases cargadas anulan el método. –

1

Lea esto para comportamiento de alineación. http://www.javacoffeebreak.com/articles/thinkinginjava/comparingc++andjava.html

Dice que los métodos finales pueden ser Inlined pero no siempre.

+0

El hecho de que ese artículo implique la interpretación como la norma - "hay compiladores just-in-time que aparecen en este escrito" sugiere que apenas está actualizado. Las máquinas virtuales han recorrido un largo camino. –

2
class A { 
    final int foo() { return 3; } 
} 

Dada esta clase, cualquier llamada a foo() se puede reemplazar con la constante "3". Cualquier máquina virtual Java1 puede hacer esto, porque la palabra clave final explícitamente dicta que no es posible tener una subclase que anule "int foo()".

Inlining El método proporciona las siguientes ventajas en el sitio de llamada:

  • Ningún método llamada
  • No envío dinámico
  • Posible constante veces el valor, por ejemplo. "a.foo() + 2" se convierte en 5 sin código ejecutado en
    runtime.

En el pasado, los programadores suelen insertar la palabra clave última exactamente por esta razón. O para facilitar mejor la creación y aumentar la velocidad de ejecución, combinarían muchos métodos más pequeños en un método más grande. Pero en muchos sentidos, tales técnicas derrotan a toda la instalación de modularización y reutilización integrada en el lenguaje de programación.

JVM moderna, al igual que Java HotSpot VM es capaz de alinear la clase sin el final. palabra clave**.

(http://java.sun.com/developer/technicalArticles/Networking/HotSpot/inlining.html)

+0

Una palabra clave (para aconsejar al compilador) para hacer una llamada a una función en línea debe tener más sentido dado que, en aras de la legibilidad, en algún momento se rompen ciertos cálculos en varias funciones mientras que al mismo tiempo se desea hacer esas llamadas en tiempo de ejecución para ahorrar mucha función-llamada sobrecarga. – mawia

+0

Respuesta de @David Rodriguez a continuación tiene sentido. Si la palabra clave en línea está destinada a ser SÓLO una SUGERENCIA para el compilador, entonces es mejor dejarla en manos del compilador y confiar en ella, que alineará la llamada siempre que sea posible sin nuestro asesoramiento. – mawia

+0

Su enlace parece estar roto, ¿podría actualizarlo? –

1

Sí, si la JVM decide hacerlo, puede hacerlo. Las formas de influir incluyen establecer el método como estático o como final.

Por supuesto, lo más importante es que la estructura del método debe ser amigable en línea. Ayuda breve, pero lo más importante es que solo necesita usar sus variables locales y sus parámetros, sin campos y llamadas a métodos mínimos a otros métodos en la misma clase.

Sin embargo, no debe considerar hacer tales optimizaciones prematuramente, en realidad podría empeorar las cosas (porque podría estar cortocircuitando otras optimizaciones potenciales). La JVM a veces se dará cuenta de que se puede insertar un método sin estas sugerencias.

6

Aunque el compilador de java puede hacer en línea (para los métodos cortos de enlace temprano) real entrando en línea se hará por el compilador JIT. El compilador JIT (HotSpot) podrá, incluso, en línea métodos virtuales. La mejor manera de interactuar con él es escribir un código simple y conciso. Es muy probable que el código que usa Reflection no permita la alineación.

Espero que ayude.

+0

¿Puede dar alguna evidencia para el compilador de Java (en oposición al compilador JÍT) llamadas de método de alineación? –

+0

* "Lo más probable es que el código que usa Reflection no permita la inserción" * - [This post] (https://stackoverflow.com/questions/14102000/cannot-change-static-final-field-using-java-reflection) parece tenerlo al revés, ¿o sí? –

5

'En C++ puedo declarar un método "en línea" y el compilador lo insertará' ... o no. El compilador es libre de hacer la función en línea o no y realmente no se puede afectar el resultado. Es solo una pista para el compilador.

En Java no existe tal cosa, el compilador (y más adelante la VM al realizar optimizaciones) puede decidir 'en línea' el método.

Tenga en cuenta que los métodos final tienen mayores posibilidades de estar en línea (el compilador no puede alinear métodos no finales, ya que pueden sobrescribirse en clases derivadas). Con la VM moderna, se puede realizar una optimización similar en tiempo de ejecución. La máquina virtual marcará el tipo (para que pueda realizar comprobaciones de tipo) e insertará el código. Solo si la verificación falla, volverá a caer en la llamada al método polimórfico no optimizado original.

+2

¡Punto importante! "en línea" no obliga al compilador a alinear su método en C. –

+0

Thx, tiene razón, olvidé que "en línea" es una sugerencia para el compilador. – CL23

+0

A veces puede forzar el compilador en línea, pero eso es específico del compilador: http://stackoverflow.com/questions/934529/c-inline-functions-using-gcc-why-the-call –

1

Al comparar una función normal y una función final (que se dice que está en línea por JVM), he visto que no hay una mejora en el rendimiento entre ellas. Tal vez la sobrecarga de la función ya es muy baja.

Nota: utilicé el algoritmo de desenfoque de cajas para evaluar el rendimiento.