library - manejo de cache en java
¿Por qué valores de almacenamiento en caché de clase Integer en el rango de-128 a 127? (5)
Con respecto a mi Pregunta anterior, ¿Por qué hacer == comparaciones con Integer.valueOf (String) para obtener resultados diferentes para 127 y 128? , sabemos que la class
Integer
tiene una memoria caché que almacena valores entre -128
y 127
.
Solo me preguntaba, ¿por qué entre -128 y 127 ?
La documentación Integer.valueOf () indicó que " almacenaba en caché valores solicitados con frecuencia " . ¿Pero los valores entre -128
y 127
frecuencia se solicitan de manera real? Pensé que los valores solicitados con frecuencia son muy subjetivos.
¿Hay alguna razón posible detrás de esto?
De la documentación también se afirmaba: "... y puede almacenar en caché otros valores fuera de este rango " .
¿Cómo se puede lograr esto?
-128 a 127 es el tamaño predeterminado. Pero javadoc también dice que el tamaño del caché Integer puede controlarse mediante la -XX:AutoBoxCacheMax=<size>
. Tenga en cuenta que solo establece un valor alto, el valor bajo siempre es -128. Esta característica fue introducida en 1.6.
En cuanto a por qué -128 a 127 - este es el rango de valores de bytes y es natural usarlo para un caché muy pequeño.
Cuando te encuentres con la clase Entero y siempre dentro del rango -128 a 127, siempre es mejor convertir el objeto entero en el valor int como se muestra a continuación.
<Your Integer Object>.intValue()
El valor entero máximo alto que se puede almacenar en caché se puede configurar a través de la propiedad del sistema, es decir, java.lang.Integer.IntegerCache.high
( -XX:AutoBoxCacheMax
). La memoria caché se implementa utilizando una matriz.
private static class IntegerCache {
static final int high;
static final Integer cache[];
static {
final int low = -128;
// high value may be configured by property
int h = 127;
if (integerCacheHighPropValue != null) {
// Use Long.decode here to avoid invoking methods that
// require Integer''s autoboxing cache to be initialized
int i = Long.decode(integerCacheHighPropValue).intValue();
i = Math.max(i, 127);
// Maximum array size is Integer.MAX_VALUE
h = Math.min(i, Integer.MAX_VALUE - -low);
}
high = h;
cache = new Integer[(high - low) + 1];
int j = low;
for(int k = 0; k < cache.length; k++)
cache[k] = new Integer(j++);
}
private IntegerCache() {}
}
La razón para almacenar en caché números enteros pequeños, si eso es lo que estás preguntando, es que muchos algoritmos usan enteros pequeños en sus cálculos, por lo que evitar la sobrecarga de creación de objetos para estos valores suele valer la pena.
La pregunta entonces es qué enteros almacenar en caché. De nuevo, hablando en general, la frecuencia con la que se usan los valores constantes tiende a disminuir a medida que aumenta el valor absoluto de la constante; todos pasan mucho tiempo utilizando los valores 1 o 2 o 10, relativamente pocos usan el valor 109 muy intensamente menos tendrá el rendimiento depende de cuán rápido uno puede obtener un Entero para 722 ... Java eligió asignar 256 ranuras que abarcan el rango de un valor de byte con signo. Esta decisión puede haber sido informada al analizar los programas existentes en ese momento, pero es probable que haya sido puramente arbitraria. Es una cantidad razonable de espacio para invertir, se puede acceder rápidamente (máscara para averiguar si el valor está en el rango del caché, luego una búsqueda rápida de tabla para acceder al caché), y definitivamente cubrirá los casos más comunes.
En otras palabras, creo que la respuesta a su pregunta es "no es tan subjetivo como pensaba, pero los límites exactos son en gran medida una decisión empírica ... y la evidencia experimental ha sido que fue lo suficientemente bueno. "
Solo me preguntaba, ¿por qué entre -128 y 127?
Se puede almacenar en caché un rango más grande de enteros, pero al menos aquellos entre -128 y 127 deben almacenarse en caché porque es obligatorio por la Especificación del lenguaje Java (énfasis mío):
Si el valor p que aparece en la casilla es verdadero, falso, un byte o un carácter en el rango de / u0000 a / u007f, o un número entero o corto entre -128 y 127 (inclusive) , entonces r1 y r2 son el resultado de dos conversiones de boxeo de p. Siempre es el caso que r1 == r2.
La razón de este requisito se explica en el mismo párrafo:
Idealmente, encajonar un valor primitivo p dado, siempre arrojaría una referencia idéntica . En la práctica, esto puede no ser factible utilizando las técnicas de implementación existentes. Las reglas anteriores son un compromiso pragmático. La cláusula final anterior requiere que ciertos valores comunes siempre estén enmarcados en objetos indistinguibles. [...]
Esto garantiza que, en la mayoría de los casos, el comportamiento será el deseado, sin imponer una penalización de rendimiento excesiva, especialmente en dispositivos pequeños . Las implementaciones menos limitadas de memoria podrían, por ejemplo, almacenar en caché todos los valores de char y cortos, así como los valores int y long en el rango de -32K a +32K.
¿Cómo puedo guardar en caché otros valores fuera de este rango?
Puede usar la -XX:AutoBoxCacheMax
JVM, que realmente no está documentada en la lista de opciones de JVM de zona -XX:AutoBoxCacheMax
disponibles . Sin embargo, se menciona en los comentarios dentro de la clase Integer
alrededor de la línea 590 :
El tamaño de la memoria caché puede controlarse mediante la
-XX:AutoBoxCacheMax=<size>
.
Tenga en cuenta que esto es específico de la implementación y puede o no estar disponible en otras JVM.