generic java
Autoboxing versus boxeo manual en Java (3)
¿Porque los resultados de microbenchmark no son confiables?
Además, el boxeo automático se realiza utilizando Integer.valueOf () y Double.valueOf (), no los constructores.
¿Por qué es la segunda pieza de código más rápido?
Map<Integer, Double> map = new HashMap<Integer, Double>();
for (int i = 0; i < 50000; i++) {
for (double j = 0.0; j < 10000; j++) {
map.put(i, j);
}
}
Map<Integer, Double> map=new HashMap<Integer, Double>();
for (int i = 0; i < 50000; i++) {
for (double j = 0.0; j < 10000; j++) {
map.put(new Integer(i), new Double(j));
}
}
Autoboxing utiliza Integer.valueOf
, que almacena internamente objetos Integer para enteros pequeños (de manera predeterminada, -128 a 127, pero el valor máximo se puede configurar con la propiedad "java.lang.Integer.IntegerCache.high"). Consulte el código fuente de Integer. .valueOf), por lo que es diferente de llamar directamente a new Integer
. Debido a que Integer.valueOf
realiza una comprobación rápida de la magnitud del valor del entero antes de llamar al new Integer
, es un poco más rápido llamar al new Integer
directamente (aunque usa más memoria si tiene muchos enteros pequeños). La asignación en Java es muy rápida, y el tiempo de hacer GC es proporcional al número de objetos vivos de corta duración (es decir, no proporcional a la cantidad de basura), por lo que GC también es muy rápido.
Pero dependiendo de la versión de JVM y de las optimizaciones habilitadas, existe la optimización de reemplazo escalar, que puede producir una diferencia de rendimiento mucho mayor al asignar objetos de corta duración (en su ejemplo, no se puede hacer la optimización, porque está almacenando los objetos en un mapa, pero en muchas otras situaciones es útil).
En las versiones recientes de JVM hay una optimización de reemplazo escalar (excepto en 1.6.0_18 donde el análisis de escape está deshabilitado temporalmente ), lo que significa que las asignaciones de objetos de corta duración pueden optimizarse. Cuando el reemplazo escalar en JVM era nuevo, alguien hizo un punto de referencia donde había un código similar al suyo. El resultado fue que el código que usaba primitivas era más rápido, el código con new Integer()
llamadas de new Integer()
explícitas era casi tan rápido como el que usaba primitivas, y el código que usaba autoboxing era mucho más lento. Esto se debió a que el autoboxing utiliza Integer.valueOf
y al menos en ese entonces la optimización de reemplazo escalar no tuvo en cuenta ese caso especial. No sé si la optimización se ha mejorado desde entonces.
Autoboxing utilizará Integer.valueOf
y Double.valueOf
. Hay una cierta sobrecarga en llamar a esos métodos (aunque eventualmente se insertará). Además, Integer.valueOf
realiza algunas comprobaciones de valores bajos para usar instancias agrupadas, lo que no suele ser una ganancia en su código (aunque podría reducir un poco el tamaño del montón). Las instancias agrupadas pueden ser una victoria en la que reducen el tamaño del montón, los tiempos de GC e incluso podrían mejorar el rendimiento de la prueba de igualdad
Pero, en general, es una microoptimización que debería, en general, ignorar.