Impacto en el rendimiento de autoboxing
-
26-09-2019 - |
Pregunta
Por lo general, el compilador genera código para realizar el boxeo y unboxing. Pero lo que hace el compilador, si no son necesarios los valores en caja? ¿Está el (Oracle estándar) compilador lo suficientemente inteligente como para optimizar la basura?
Tome un vistazo a este método:
public static void requireInRange(int index, Object[] array) {
if(index < 0 || index >= array.length)
throw new IndexOutOfBoundsException();
}
La información sólo es relevante es la array.length
, por lo que sería inútil a la caja de cada valor de una matriz, por ejemplo. Al igual que en este código:
int[] anArray = {3, 4, 2};
requireInRange(3, anArray);
¿El compilador realidad inserción de código para el boxeo cada valor de la matriz?
Solución
No hay autoboxing en el código. De hecho, teniendo en cuenta:
public static void requireInRange(int index, Object[] array) {
...
}
int[] anArray = {3, 4, 2};
requireInRange(3, anArray); // DOES NOT COMPILE!!!
Mientras que un int
puede autoboxed a un Integer
, un int[]
hace no get autoboxed a Integer[]
por Java. Puede escribir funciones de biblioteca para hacer esto, pero el lenguaje no facilitar esta conversión.
Esto es de hecho la fuente de muchos confusión con respecto a, por ejemplo, Arrays.asList(anIntArray)
está "roto", porque en lugar de devolver un List<Integer>
, lo que se devuelve es de hecho una List<int[]>
de un elemento.
¿Pero qué sobre el rendimiento ???
Una cita de Guía del lenguaje Java / Autoboxing :
No es apropiado utilizar autoboxing y unboxing para la computación científica, u otro código numérico sensibles al rendimiento. Un
Integer
no es un sustituto para unint
; autoboxing y el desenfoque unboxing la distinción entre tipos primitivos y los tipos de referencia, pero no lo eliminan.
En resumen, cada vez que autoboxing sucede, el rendimiento definitivamente se necesita un poco de un golpe. Ciertas cosas ayuda a aliviar este, por ejemplo, el mecanismo de caché integrada en estos tipos. Es por esto que se obtiene lo siguiente:
System.out.println(
((Integer) 0) == ((Integer) 0)
);
// true
System.out.println(
((Integer) 10000) == ((Integer) 10000)
);
// false (implementation-specific)
Lo que pasó aquí es que cuando 0
es automáticamente en caja, sin nueva ejemplo Integer
se crea realmente: los valores en cierto rango es caché para autoboxing propósitos, con el desempeño de ayuda. 10000
en la mayor aplicación probablemente cae fuera de este rango, pero algunas implementaciones de JVM hacer le permiten especificar el rango de caché si es necesario.
Pero sólo quiero obtener la longitud de la matriz !!!
Hay muchas maneras de facilitar su requireInRange
para trabajar con cualquier tipo de matrices. Desafortunadamente trabajar con conjunto de primitivas de Java a menudo significa un montón de repetición. Esto significa que debe ofrecer sobrecargas para int[]
, boolean[]
, byte[]
, Object[]
, etc por separado.
Una opción más concisa es utilizar la reflexión, pero esto tiene sus ventajas y desventajas. En términos generales, la reflexión no debe ser la solución preferida para la mayoría de los escenarios.
Una vez dicho esto, java.lang.reflect.Array
tiene un int getLength(Object array)
static
método que puede devolver la longitud de CUALQUIER array. No es typesafe (como la mayoría mecanismo de reflexión son); pasando una compila no matriz, pero lanza IllegalArgumentException
en tiempo de ejecución.
preguntas relacionadas
- Gestión de código altamente repetitivo y documentación en Java - ( "inspirado" por
java.util.Arrays
)
Otros consejos
cifrará el compilador realmente inserto para el boxeo cada valor de la matriz?
El compilador rechazará el código porque un int[]
no se puede pasar en un método que toma un parámetro Object[]
.
Autoboxing sucede sólo para valores primitivos individuales, no para las matrices enteras.
En caso de duda, se puede asumir que el compilador no optimizar el código. Generalmente se hace una traducción literal del código.
Además, en caso de duda youc una suponer la JVM hace un muy buen trabajo de optimización de código en tiempo de ejecución. Yo no asuma que hace ninguna diferencia a menos que tenga una buena razón (tal como perfilador) para sospechar que es un problema.