Quand la corbeille contenu HashMap pour éviter la dégradation des performances?
-
19-09-2019 - |
Question
Je suis woking sur Java avec un grand (en millions) hashmap qui est en fait construit avec une capacité de 10.000.000 et un facteur de charge de .75 et il est utilisé pour mettre en cache certaines valeurs
puisque les valeurs mises en cache deviennent inutiles avec le temps (pas plus accédé) mais je ne peux pas enlever les inutiles tandis que sur la façon dont je voudrais tout vider le cache lorsque ses performances commence à se dégrader. Comment puis-je décider quand il est bon de le faire?
Par exemple, avec 10 millions capacité et .75 dois-je vider quand il atteint 7,5 millions d'éléments? Parce que j'ai essayé différentes valeurs de seuil, mais je voudrais avoir une une analyse.
Je l'ai déjà testé le fait que emping quand il est tout à fait complet est un coup de pouce pour perfomance (2-3 premières itérations de l'algorithme après la lingette suffit de remplir le récupérer, il commence à courir plus vite que avant la lingette)
EDIT: INFO ADDITIONNELLE
Le hashmap a longtemps que les clés et flottent comme des valeurs. Il contient corrélation mises en cache des contenus, car il est un produit scalaire de vecteurs d'étiquette que je voulais les mettre en cache (pour augmenter les performances).
Donc, fondamentalement, ce que je fais est de calculer une clé long
en utilisant les codes de hachage des 2 contenus:
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;
}
et l'utiliser pour récupérer les valeurs stockées. Ce qui se passe est que, puisque c'est un contenu classification hiérarchique sont fusionnés et leurs valeurs de corrélation avec d'autres contenus ne sont pas nécessaires plus .. voilà pourquoi je veux essuyer la hashmap de temps en temps, pour éviter la dégradation due à des valeurs inutiles à l'intérieur.
L'utilisation d'un WeakHashMap
va effacer les données imprévisiblement aussi quand ils sont encore nécessaires .. Je n'ai pas le contrôle.
Merci
La solution
Pourquoi ne pas utiliser un cache LRU? D'après la documentation LinkedHashMap Java:
Un constructeur spécial est prévu pour créer une carte de hachage liée dont l'ordre de l'itération est l'ordre dans lequel son les entrées du dernier accès, de moins récemment accédé à plus récemment (accès ordre). Cette genre de carte est bien adapté à la construction caches LRU. Invoquer le put ou obtenir procédé conduit à un accès à la entrée correspondant (en supposant que existe après l'invocation battant). Procédé putAll génère un accès d'entrée pour chaque cartographier sur la carte spécifiée, dans la ordonner que les correspondances clé-valeur sont fournie par l'entrée de la carte spécifiée ensemble iterator. Aucune autre méthode générer entrée accède. Dans en particulier, les opérations sur collecte-vues ne touchent pas la ordre de l'itération du plan de support.
Donc, fondamentalement, tous les temps en temps que votre carte est trop grande, il suffit de supprimer les premières valeurs de x que le iterator vous donne.
Voir la documentation pour removeEldestEntry
que cela soit fait automatiquement pour vous.
Voici le code qui démontre:
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}
}
Autres conseils
Avez-vous enquêté WeakHashMaps ? Le garbage collector peut déterminer quand enlever des choses et il peut vous donner un substitut acceptable plutôt que de coder quelque chose vous-même.
Cet article contient des informations plus utiles.
Vous pouvez utiliser Google Collections' pour faire MapMaker une carte avec des références douces et un délai d'attente spécifique.
Références douces « sont effacées à la discrétion du collecteur des ordures en réponse à la demande de mémoire ».
Exemple:
ConcurrentMap<Long, ValueTypeHere> cacheMap = new MapMaker()
.concurrencyLevel(32)
.softValues()
.expiration(30, TimeUnit.MINUTES)
.makeMap();
Vous pouvez également spécifier weakKeys si vous voulez faire ses clés agissent comme ceux dans un WeakHashMap.