Domanda

Sono woking su Java con una grande HashMap (milioni) che è in realtà costruito con una capacità di 10.000.000 e un fattore di carico di 0,75 ed è utilizzato per memorizzare nella cache alcuni valori

poiché i valori memorizzati nella cache diventano inutili col tempo (non acceduto più), ma non riesco a rimuovere quelle inutili, mentre sulla strada mi piacerebbe completamente vuota la cache quando le sue prestazioni comincia a degradare. Come posso decidere quando è buono per farlo?

Ad esempio, con una capacità di 10 milioni di persone e .75 devo svuotarlo quando raggiunge 7,5 milioni di elementi? Perché ho provato diversi valori soglia ma desidero avere uno analitico.

Ho già provato il fatto che emping quando è abbastanza completo è una spinta per perfomance (primi 2-3 iterazioni algoritmo dopo la salvietta appena riempirlo di nuovo, allora comincia a correre più velocemente rispetto a prima della wipe)

EDIT: Ulteriori informazioni

Il hashmap trovi lungo come chiavi e galleggiante come valori. Esso contiene la correlazione cache di contenuti, dal momento che si tratta di un prodotto scalare di vettori tag ho voluto mettere in cache loro (per aumentare le prestazioni).

Quindi, in pratica quello che faccio è quello di calcolare una chiave long utilizzando i codici hash dei contenuti 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;
}

e utilizzarlo per recuperare i valori memorizzati. Quello che succede è che, poiché si tratta di un clustering gerarchico contenuti vengono uniti ei loro valori di correlazione con altri contenuti non sono necessari più .. è per questo che voglio pulire il HashMap di tanto in tanto, per evitare il degrado a causa di valori inutili al suo interno.

Utilizzando un WeakHashMap sarà imprevedibilmente cancellare i dati anche quando sono ancora necessari .. non ho controllo su di esso.

Grazie

È stato utile?

Soluzione

Perché non usare un LRU cache? Dalla documentazione LinkedHashMap di Java:

  

Un costruttore speciale è previsto per   creare una mappa di hash legato il cui ordine   di iterazione è l'ordine in cui il suo   voci stati aperti, da   meno di recente accesso a   più di recente (accesso-ordine). Questo   tipo di carta è particolarmente adatto alla costruzione   cache LRU. Invocare put o ottenere   metodo comporta un accesso alla   corrispondente voce (supponendo che   esiste dopo l'invocazione   completa). Il metodo putAll   genera una voce per ogni accesso   mappatura nella mappa specificato, nel   ordinare che mappature chiave-valore sono   fornito dalla ingresso della mappa specificata   iteratore set. Non ci sono altri metodi   generare ingresso accessi. Nel   particolare, le operazioni di   raccolta-vista non influiscono sulla   ordine di iterazione della mappa di backup.

Quindi, fondamentalmente, ogni tanto un po 'come il vostro mappa diventa troppo grande, basta eliminare i primi valori di x che l'iteratore ti dà.

Si veda la documentazione per removeEldestEntry di avere questo fatto per voi automaticamente.

Ecco il codice che dimostra:

 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}
  }

Altri suggerimenti

Avete indagato WeakHashMaps ? Il garbage collector può determinare quando per rimuovere cose e può dare un sostituto accettabile piuttosto che codifica qualcosa di te stesso.

Questo articolo ha informazioni più utili.

Si consiglia di utilizzare Google Collezioni MapMaker per fare una mappa con riferimenti morbide e un timeout specifica.

I riferimenti soft "vengono cancellati a discrezione del garbage collector in risposta alla domanda di memoria".

Esempio:

ConcurrentMap<Long, ValueTypeHere> cacheMap = new MapMaker()
    .concurrencyLevel(32)
    .softValues()
    .expiration(30, TimeUnit.MINUTES)
    .makeMap();

È inoltre possibile specificare weakKeys se si vuole fare i suoi tasti si comportano come quelle di un WeakHashMap.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top