Domanda

Ho bisogno di oggetti nella cache di Java che utilizza una percentuale di qualunque cosa di RAM disponibile.Sono consapevole che altri hanno fatto questa domanda, ma nessuna delle risposte a soddisfare i miei requisiti.

I miei requisiti sono:

  • Semplice e leggero
  • Non molto più lento di un normale HashMap
  • Utilizzare LRU, o alcuni criteri di eliminazione che approssima LRU

Ho provato LinkedHashMap, tuttavia si richiede di specificare un numero massimo di elementi, e non so quanti elementi ci vorrà per riempire la RAM disponibile (le loro dimensioni variano sensibilmente).

Il mio approccio è quello di utilizzare Google Raccolta del Cartografo come segue:

Map<String, Object> cache = new MapMaker().softKeys().makeMap();

Questo sembrava attraente come dovrebbe eliminare automaticamente gli elementi quando si ha bisogno di più RAM, però c'è un problema serio:il suo comportamento è quello di riempire tutta la RAM disponibile, al punto che il GC inizia a dimenarsi e tutta l'app di performance peggiora drasticamente.

Ho sentito parlare di cose come EHCache, ma sembra abbastanza pesante per quello che mi serve, e non so se è abbastanza veloce per la mia applicazione (ricordando che la soluzione non può essere notevolmente più lenta di una HashMap).

È stato utile?

Soluzione

Ho esigenze simili a voi - la concorrenza (su 2 hexacore Cpu) e LRU o simili - e anche cercato di Guava Cartografo.Ho trovato softValues() molto più lento rispetto weakValues(), ma sia fatta la mia app terribilmente lento quando la memoria è piena.

Ho provato WeakHashMap ed è stato meno problematico, stranamente, ancora più veloce rispetto all'utilizzo di LinkedHashMap come LRU cache tramite il suo removeEldestEntry() metodo.

Ma il metodo più rapido per me è ConcurrentLinkedHashMap che ha reso la mia app 3-4 (!!) volte più veloce di qualsiasi altra cache ho provato.Gioia, dopo giorni di frustrazione!In apparenza è stata incorporata in Guava del Cartografo, ma la LRU funzione non è in Guava r07 a qualsiasi velocità.Spero che funziona per voi.

Altri suggerimenti

Ho implementato cache Serval ed è probabilmente il più difficile l'attuazione di una nuova origine dati o di thread, la mia raccomandazione è di usare JBoss-cache o di un altro ben noto lib caching. Così potrete dormire bene senza problemi

  

Ho sentito parlare di cose come EHCache, ma sembra abbastanza pesante per quello che mi serve, e non sono sicuro se è abbastanza veloce per la mia applicazione (ricordando che la soluzione non può essere notevolmente più lento di un HashMap).

Io davvero non so se si può dire che EHCache è pesante. Almeno, non ritengo EHCache come tale, soprattutto quando si utilizza un Memory Store (che è supportato da un LinkedHashMap ed è, naturalmente, la memorizzazione nella cache più veloce opzione). Si dovrebbe fare un tentativo.

Credo MapMaker sta per essere l'unico modo ragionevole per ottenere quello che stai chiedendo. Se "il GC inizia a thrash e le prestazioni dell'intera applicazione peggiora drammaticamente," si dovrebbe passare un po 'di tempo impostando correttamente i vari parametri di ottimizzazione. Questo documento può sembrare un po 'intimidatorio in un primo momento, ma in realtà è scritto molto chiaramente ed è una miniera di informazioni utili su GC:

http://java.sun.com/j2se/reference/whitepapers /memorymanagement_whitepaper.pdf

Non so se questa sarebbe una soluzione semplice, soprattutto in confronto con EHCache o simili, ma ho guardato il Javolution biblioteca? Non è progettato per quanto tale, ma nel pacchetto javolution.context hanno un modello Allocatore che può riutilizzare oggetti senza la necessità di garbage collection. In questo modo a mantenere la creazione di oggetti e la raccolta dei rifiuti al minimo, una caratteristica importante per la programmazione in tempo reale. Forse si dovrebbe dare un'occhiata e cercare di adattarlo al vostro problema.

  

Questo sembrava interessante come dovrebbe   eliminare automaticamente elementi quando   ha bisogno di più RAM, tuttavia c'è un   problema serio: il suo comportamento è quello di   riempire tutta la RAM disponibile

Mediante softkey consente solo il garbage collector per rimuovere oggetti dalla cache quando nessun altro oggetto loro riferimento (cioè, quando l'unica cosa riferimento alla chiave di cache è la cache stessa). Essa non garantisce alcun altro tipo di espulsione.

La maggior parte delle soluzioni trovate saranno funzionalità aggiunte in cima alle classi Java Mappa, tra cui EHCache.

Avete guardato il Commons-collezioni LRUMap?

Si noti che non v'è un questione aperta contro MapMaker per fornire funzionalità LRU / MRU. Forse si può esprimere la tua opinione, cosi '

Utilizzando la cache esistente, negozio WeakReference piuttosto che normali refererences oggetti.

Se GC inizia a corto di spazio libero, saranno rilasciati i valori detenuti da WeakReferences.

In passato ho usato JCS . È possibile impostare il configurazione per cercare di soddisfare le vostre esigenze. Non sono sicuro se questo sarà soddisfare tutte le vostre esigenze / bisogni, ma ho trovato ad essere abbastanza potente quando l'ho usato.

Non si può "eliminare elementi" ci si può fermare solo difficile farvi riferimento e attendere che il GC per pulirli, in modo da andare avanti con Google Collezioni ...

Io non sono a conoscenza di un modo semplice per scoprire le dimensioni di un oggetto in Java. Pertanto, non credo che troverete un modo per limitare una struttura di dati dalla quantità di RAM sta prendendo.

In base a questa ipotesi, sei bloccato con limitandolo per il numero di oggetti memorizzati nella cache. Io suggerirei l'esecuzione di simulazioni di alcuni scenari di utilizzo di vita reale e la raccolta di statistiche sui tipi di oggetti che vanno nella cache. Quindi è possibile calcolare la dimensione statisticamente media, e il numero di oggetti che può permettersi di cache. Anche se è solo un'approssimazione della quantità di RAM che si desidera dedicare alla cache, potrebbe essere sufficiente.

Per quanto riguarda l'attuazione della cache, nel mio progetto (un'applicazione prestazioni critiche) stiamo usando EHCache, e personalmente non trovo che sia pesante a tutti.

In ogni caso, eseguire diversi test con diverse configurazioni (per quanto riguarda le dimensioni, la politica di sfratto, ecc) e scoprire che cosa funziona meglio per voi.

Caching qualcosa, SoftReference forse il modo migliore fino ad ora posso immaginare.

In alternativa è possibile reinventare un oggetto-piscina. Che ogni oggetto che si non utilizza, non è necessario per distruggerla. Ma per salvare CPU, piuttosto che risparmiare memoria

Supponendo che si desidera la cache di essere thread-safe, allora si dovrebbe esaminare l'esempio di cache nel libro di Brian Goetz "Java Concurrency in Practice". Non posso raccomandare altamente questo.

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