En Java hay una diferencia de rendimiento entre referencia a un campo a través captador frente a través de una variable?

StackOverflow https://stackoverflow.com/questions/1195849

Pregunta

¿Hay alguna diferencia entre hacer

Field field = something.getSomethingElse().getField();
if (field == 0) {
//do something    
}
somelist.add(field);

frente

if (something.getSomethingElse().getField() == 0) {
//do something    
}
somelist.add(something.getSomethingElse().getField());

Hacer referencias al campo a través de captadores incurrir en una penalización en el rendimiento o es la misma que hace referencia a una variable asignada? entiendo que la variable es sólo una referencia al espacio de memoria, por lo que el comprador debería acaba de ser otra manera de conseguir en ese espacio de memoria.

Tenga en cuenta que esto es una cuestión académica (escuela de curiosidad) en lugar de un carácter práctico.

¿Fue útil?

Solución

Suponiendo que getSomethingElse() se define como

public SomethingElse getSomethingElse() {
    return this.somethingElse;
}

diferencia de rendimiento será mínimo (o cero si obtendrá en línea). Sin embargo, en la vida real no siempre se puede estar seguro de que es el caso - que puede haber algún tipo de procesamiento sucede en segundo plano (no necesariamente en el objeto en sí, sino, por ejemplo, a través de proxy AOP). Por tanto, salvar el resultado en la variable para el acceso de repetición puede ser una buena idea.

Otros consejos

Es un detrimento insignificante. No se preocupen con él demasiado o te vas a caer presa de la optimización prematura. Si su aplicación es lenta, esta no es la razón por qué.

Hay una diferencia en la que las variables de acceso a través de los resultados de captadores en una llamada al método. La JVM podría concebiblemente ser capaz de optimizar la llamada al método de distancia en algunas circunstancias, pero es una llamada al método.

Dicho esto, si el mayor cuello de botella o la prestación del problema en su código es cabeza de métodos de acceso, diría que no tiene mucho de qué preocuparse.

Hay una penalización de rendimiento (que puede ser tan pequeño que es despreciable) Sin embargo, la JVM puede inline esta y todas las llamadas para mejorar el rendimiento.

Sería mejor si se deja la segunda manera.

No, si usted tiene una buena JVM, como HotSpot de Sun. Lo hará en línea y compilar (a código nativo) los captadores.

El uso de captadores es en general una muy buena práctica, como medida defensiva, y la ocultación de información general.

Un punto a tener en cuenta si el uso de Java para escribir aplicaciones de Android está aquí: http://developer.android.com/training/articles/perf-tips .html # GettersSetters

  

En las lenguas nativas como C ++ es una práctica común el uso de captadores (i =   getCount ()) en lugar de acceder al campo directamente (i = mcount). Esta   es un excelente hábito para C ++ y, a menudo se practica en otro objeto   lenguajes orientados como C # y Java, ya que el compilador puede por lo general   inline el acceso, y si es necesario para restringir el acceso o el campo de depuración   puede agregar el código en cualquier momento.

     

Sin embargo, esta es una mala idea en Android. llamadas a métodos virtuales son   caro, mucho más que las búsquedas de campo de instancia. Es razonable   a seguir las prácticas comunes de programación orientados a objetos y tienen   captadores y definidores en la interfaz pública, pero dentro de una clase se   siempre debe acceder a los campos directamente.

     

Sin JIT, el acceso de campo directo es aproximadamente 3 veces más rápido que la invocación de una   captador trivial. Con el JIT (donde el acceso directo de campo es tan barato como   el acceso a), acceso directo ámbito local es aproximadamente 7 veces más rápido que   invocando un captador trivial.

     

Tenga en cuenta que si usted está utilizando ProGuard, puede tener lo mejor de ambos   mundos porque ProGuard pueden inline descriptores de acceso para usted.

Si el método es un captador sencilla sin procesamiento involucrado no es un problema. Si se trata de una amplia cálculo, una propiedad no haría lo que quiere de todos modos.

La única vez que me preocuparía por cualquier diferencia está en un bucle estrecho con un gran número de iteraciones (muchos miles). Incluso entonces esto es probablemente sólo un problema si utiliza aspectos para tejer procesamiento adicional (por ejemplo, la tala), esto puede implicar la creación de miles de objetos adicionales (por ejemplo joinpoints y parámetros autoboxing) y los problemas resultantes de GC.

Yo no me preocuparía por la diferencia de rendimiento. Usted sería mejor no pensar en ello y en lugar de dedicar tiempo a perfilar su código en un escenario realista. muy probablemente se dará cuenta de que las partes lentas de su programa no son donde se piensa que son.

Este post habla de la CLI de VM en lugar de la JVM, pero cada uno es capaz de hacer cosas similares, por lo que creen que es relevante.

Estoy manejo de este problema particular de una manera especial para mi JIT. Tenga en cuenta que la descripción aquí es conceptual y el código implementa de una manera ligeramente diferente por razones de rendimiento. Cuando cargo un montaje, hago una nota en el descriptor de método si simplemente devuelve un campo miembro. Cuando JIT otros métodos más tarde, puedo reemplazar todas las instrucciones call a estos métodos en el código de bytes con una instrucción ldfld antes de pasarlo al generador de código nativo. De esta manera, puedo:

  1. ahorrar tiempo en el JIT (ldfld tarda menos tiempo de procesador a JIT que call).
  2. propiedades
  3. En línea, incluso en el línea de base compilador .
  4. En general garantía de que con el patrón de propiedades públicas / privadas campos no incurrirá en una penalización de rendimiento de ninguna clase cuando se separa el depurador. (Cuando se adjunta un depurador no puedo inline los descriptores de acceso.)

No tengo ninguna duda de que los grandes nombres de las tecnologías de máquinas virtuales ya están implementando algo similar a (y probablemente mejor que) esto en sus productos.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top