java - google - udacity android jetpack
Desempeño de Android: "Evitar compiladores/instaladores internos" (7)
Aunque b.innerObject
es más rápido, a medida que avanza la tecnología (mejor cpus, JIT, etc.) la diferencia entre las dos opciones se reduce.
El único punto donde puede importar es cuando se realiza en ciclos intensivos que se ejecutan todo el tiempo. Por ejemplo, en el método onDraw
de un juego, cuando onDraw
cientos de objetos.
Solo lea esto en el sitio de desarrollo:
Evitar los recolectores internos / Setters
En los lenguajes nativos como C ++, es una práctica común utilizar getters (por ejemplo, i = getCount ()) en lugar de acceder directamente al campo (i = mCount). Este es un hábito excelente para C ++, ya que el compilador generalmente puede alinear el acceso, y si necesita restringir o depurar el acceso al campo, puede agregar el código en cualquier momento.
En Android, esta es una mala idea. Las llamadas a métodos virtuales son costosas, mucho más que las búsquedas de campo de instancias. Es razonable seguir prácticas comunes de programación orientada a objetos y tener getters y setters en la interfaz pública, pero dentro de una clase siempre se debe acceder directamente a los campos.
Sin un JIT, el acceso directo al campo es aproximadamente 3 veces más rápido que invocar un getter trivial. Con el JIT (donde el acceso directo en el campo es tan barato como acceder a un local), el acceso directo al campo es aproximadamente 7 veces más rápido que invocar un getter trivial. Esto es cierto en Froyo, pero mejorará en el futuro cuando el JIT incorpore métodos getter.
Entonces, ¿está diciendo que usaría el acceso de campo dentro de la clase?
public class MyObject {
public Object innerObject; // This would be private if I was using a getter
public void doSomeStuff(){
if(innerObject){ // Within class access like this
// ....
}
}
public Object getInnerObject(){ // This would be removed if I was using field access
return innerObject;
}
}
Pero, ¿qué pasa con el acceso desde otro objeto ?
public class SecondObject {
public void doSecondSomething(){
MyObject ob = new MyObject();
Object inner;
//This is my question basically (from an Android performance perspective)
inner = ob.getInnerObject();
// OR
inner = b.innerObject
}
}
El impacto en el rendimiento del uso de getters y setters internos también se aplica a getters y setters externos.
Sin embargo, en el caso externo, los captadores y establecedores tienen beneficios significativos en otras áreas; por ejemplo, preservando la encapsulación, reduciendo el acoplamiento dañino, haciendo que su código sea más fácil de mantener, y así sucesivamente. Por lo tanto, generalmente se considera una buena práctica utilizar getters y setters a pesar del impacto en el rendimiento que esto pueda ocasionar.
El golpe de rendimiento es el resultado de las limitaciones de la generación actual de compiladores JIT de Android más antiguos. Esta situación seguramente mejorará con Gingerbread. (Referencia - https://.com/a/4930538/139985 ... y tenga en cuenta quién escribió esa respuesta!)
En general, es una mala idea "sintonizar" tu código para una plataforma inferior, especialmente si hay una posibilidad razonable de que haya una mejor a la vista.
En lo que this.field
rendimiento, no hay diferencia en el acceso a este this.field
o a ese that.field
.
La sensación de que un campo de instancia es más accesible para el objeto que la aloja es solo una ilusión de sintaxis.
OO sabio, en serio, ¿cuán compleja puede ser una aplicación de Android? Muchos de los mantras de OO provienen de la construcción de aplicaciones de monstruos. ¿Cuál es el problema si su pequeña aplicación usa objetos como estructuras?
E incluso en una gran aplicación, mientras esté en casa, y todo el código fuente que accede a un campo esté disponible para la refactorización, no hay ningún problema en exponer los campos.
Getters y Setters siempre tienen una sobrecarga, ya que son llamadas a funciones. Cuando está en el mismo objeto, puede optimizar su código al no usarlo, ya que sabe para qué se utiliza y no necesita abstraerlo / encapsularlo de su propio objeto.
Creo que también debes mirarlo desde una perspectiva diferente:
¿A no tener un getter / setter romperá las prácticas comunes de Ups? No querrá tener referencias directas si está creando objetos / módulos que otros usarán.
Realmente no desea utilizar getters / setters demasiadas veces como al final, a menos que el sh! * Sea optimizado fuera de sus llamadas de función tendrá sobrecarga.
Realmente necesita optimizar en cada caso, si estoy construyendo dos módulos donde solo se accede a algunos componentes, podría crear un campo estático, de lo contrario me quedaré con getters / setters
Para el registro, otro problema con setter y getter (en Java) es que son dolorosamente feos de usar.
Digamos que el próximo ejercicio, necesitamos modificar un campo insider un campo de un objeto
En java es:
object.getField().getSubField().setField3("hello"); // ugly
Mientras que en C # el mismo código es (incluso con encapsulamiento)
object.Field.SubField.Field3="hello"; // fine
Entonces, usar el campo público en Java (o Android) es mucho más limpio:
object.field.subfield.field3="hello"; // fine too
Tenga en cuenta que esas consideraciones de rendimiento son relevantes solo si se accede al miembro en cuestión miles de veces por segundo.
Un buen ejemplo en el que el acceso directo puede ser una buena idea es el scenegraph de un juego ( libgdx )
public abstract class Actor {
public Group parent;
public final String name;
public boolean touchable = true;
public float x;
public float y;
public float width;
public float height;
public float originX;
public float originY;
public float scaleX = 1;
public float scaleY = 1;
public float rotation;
public final Color color = new Color(1, 1, 1, 1);
// this is faster
inner = b.innerObject
// but this won''t hurt performance much because
// it''s assumed that it will be rare
inner = ob.getInnerObject();