Cuando a la basura contenidos HashMap para evitar la degradación del rendimiento?
-
19-09-2019 - |
Pregunta
Estoy woking en Java con un HashMap grandes (millones) que en realidad está construido con una capacidad de 10.000.000 y un factor de carga de 0,75 y se utiliza para almacenar en caché algunos valores
ya que los valores almacenados en caché se vuelven inútiles con el tiempo (no accedí a más), pero no puedo quitar los inútiles, mientras que en el camino me gustaría completamente vacía la caché cuando su rendimiento comienza a degradarse. ¿Cómo puedo decidir cuando es bueno hacerlo?
Por ejemplo, con capacidad de 10 millones y 0,75 debo vaciarlo cuando alcanza 7,5 millones de elementos? Porque he intentado varios valores de umbral, pero me gustaría tener uno analítica.
Ya he probado el hecho de que emping cuando es bastante completo es un impulso para la perfomance de (primeras 23 iteraciones del algoritmo después de la toallita sólo tiene que rellenar de nuevo, entonces empieza a correr más rápido que antes la toallita)
EDIT: INFORMACIÓN ADICIONAL
El HashMap tiene siempre y cuando las llaves y flotar como valores. Contiene correlación en caché de contenido, ya que es un producto escalar de vectores de etiquetas que quería caché ellos (para aumentar el rendimiento).
Así que básicamente lo que hago es para calcular una clave long
utilizando los hashcodes de los contenidos 2:
static private long computeKey(Object o1, Object o2)
{
int h1 = o1.hashCode();
int h2 = o2.hashCode();
if (h1 < h2)
{
int swap = h1;
h1 = h2;
h2 = swap;
}
return ((long)h1) << 32 | h2;
}
y utilizarlo para recuperar los valores almacenados. Lo que ocurre es que, dado que se trata de una agrupación jerárquica contenidos se fusionaron y sus valores de correlación con otros contenidos no son necesarios más .. es por eso que quiero para limpiar el HashMap de vez en cuando, para evitar la degradación debido a los valores inútiles en su interior.
El uso de un WeakHashMap
será impredecible eliminar datos también cuando todavía son necesarios .. no tengo control sobre él.
Gracias
Solución
¿Por qué no utilizar un caché LRU? A partir de la documentación LinkedHashMap de Java:
Un constructor especial aquí suministrada crear un mapa hash ligado cuyo orden de iteración es el orden en que su las entradas se accedió por última, desde menos recientemente visitada a más recientemente (acceso en el orden). Esta tipo de mapa es muy adecuado para la construcción cachés LRU. La invocación de la opción de venta o conseguir método da como resultado un acceso a la entrada correspondiente (suponiendo que existe después de la invocación completa). El método putAll genera un acceso de entrada para cada mapeo en el mapa especificado, en el orden de que las asignaciones de valores clave son proporcionado por la entrada del mapa especificado conjunto iterador. No hay otros métodos generar accesos de entrada. En particulares, las operaciones en recogida de vistas no afectan a la orden de iteración de la correlación de respaldo.
Así que, básicamente, de vez en cuando como su mapa se hace demasiado grande, basta con borrar los primeros valores de x que el iterador le da.
Consulte la documentación de removeEldestEntry
que esto se haga de forma automática.
Este es el código que se muestra:
public static void main(String[] args) {
class CacheMap extends LinkedHashMap{
private int maxCapacity;
public CacheMap(int initialCapacity, int maxCapacity) {
super(initialCapacity, 0.75f, true);
this.maxCapacity = maxCapacity;
}
@Override
protected boolean removeEldestEntry(Map.Entry eldest) {
return size()>maxCapacity;
}
}
int[] popular = {1,2,3,4,5};
CacheMap myCache = new CacheMap(5, 10);
for (int i=0; i<100; i++){
myCache.put(i,i);
for (int p : popular) {
myCache.get(p);
}
}
System.out.println(myCache.toString());
//{95=95, 96=96, 97=97, 98=98, 99=99, 1=1, 2=2, 3=3, 4=4, 5=5}
}
Otros consejos
¿Ha investigado WeakHashMaps ? El recolector de basura puede determinar cuándo se debe quitar cosas y se le puede dar un sustituto aceptable en lugar de la codificación algo por sí mismo.
Este artículo tiene la información más útil.
Es posible que desee utilizar Google Colecciones Map Maker para hacer un mapa con referencias suaves y un tiempo de espera específico.
Las referencias blandas "se borran a discreción del recolector de basura en respuesta a la demanda de memoria."
Ejemplo:
ConcurrentMap<Long, ValueTypeHere> cacheMap = new MapMaker()
.concurrencyLevel(32)
.softValues()
.expiration(30, TimeUnit.MINUTES)
.makeMap();
También puede especificar weakKeys si usted quiere hacer sus teclas actúan como los de un WeakHashMap.