2013-07-21 8 views
15

Nella mia applicazione io uso un dizionario (che supporta l'aggiunta, la rimozione, l'aggiornamento e la ricerca) dove entrambe le chiavi e i valori sono o possono essere resi serializzabili (i valori possono essere abbastanza grafici ad oggetti di grandi dimensioni). Sono arrivato a un punto in cui il dizionario è diventato così grande che tenerlo completamente in memoria ha iniziato a scatenare occasionalmente OutOfMemoryException (a volte nei metodi del dizionario, e talvolta in altre parti del codice).Un dizionario in grado di salvare i suoi elementi accessibili meno spesso su un disco

Dopo un tentativo di sostituire completamente il dizionario con un database, le prestazioni sono scese a un livello inaccettabile.

L'analisi dei modelli di utilizzo del dizionario ha mostrato che di solito una parte più piccola dei valori è "calda" (si accede abbastanza spesso) e il resto (una parte più grande) è "freddo" (accesso raramente o mai). È difficile dire quando viene aggiunto un nuovo valore se sarà caldo o freddo, inoltre, alcuni valori possono migrare avanti e indietro tra le parti calde e fredde nel tempo.

Penso di aver bisogno di un'implementazione di un dizionario in grado di scaricare i suoi valori a freddo su un disco in un evento di memoria insufficiente, quindi ricaricarli alcuni su richiesta e tenerli in memoria fino al prossimo evento di memoria insufficiente si verifica quando il loro stato caldo/freddo sarà rivalutato. Idealmente, l'implementazione dovrebbe regolare in modo ordinato le dimensioni delle parti calde e fredde e l'intervallo di risciacquo in base al profilo di utilizzo della memoria nell'applicazione per massimizzare le prestazioni complessive. Poiché nell'applicazione esistono diverse istanze di un dizionario (con diversi tipi di chiavi/valori), penso che potrebbero aver bisogno di coordinare i loro flussi di lavoro.

Potrebbe suggerire come implementare un tale dizionario?

+5

Hai mai pensato di aggiungere cache all'approccio db? Penso che la cache standard con scadenza scorrevole possa migliorare le prestazioni. – empi

risposta

0

Solo un'idea - che non ha mai fatto e mai utilizzato System.Runtime.Caching:

Implementare un wrapper MemoryCache che sarà:

  1. Aggiungere elementi con un callback sfratto specificato. Il callback inserirà gli elementi eliminati nel database.
  2. Scarica l'elemento dal database e reinserito in MemoryCache se l'elemento è assente in MemoryCache durante il recupero.
  3. Se ci si aspetta un sacco di richieste di articoli mancanti nel database e nella memoria, sarà probabilmente necessario implementare un filtro di fioritura o le chiavi di cache anche per gli articoli presenti/mancanti.
0

Ho un problema simile in passato.

Il concetto che si sta cercando è una cache di lettura con una coda LRU (usata di recente o utilizzata più di recente).

Is it there any LRU implementation of IDictionary?

Come si aggiungono le cose al dizionario tenere traccia di quali quelli in cui utilizzato meno di recente, rimuoverli dalla memoria e persistono quelli su disco.

2

Compilare per 64 bit, distribuire su 64 bit, aggiungere memoria. Tienilo in memoria.

Prima di coltivare la propria puoi alternativamente guardare a WeakReference http://msdn.microsoft.com/en-us/library/ms404247.aspx. Ovviamente richiederà di ricostruire quegli oggetti che sono stati recuperati, ma si dovrebbe sperare che quelli che sono recuperati non siano usati molto. Viene fornito con l'avvertenza che le sue stesse guide indicano di non utilizzare riferimenti deboli come soluzione automatica ai problemi di gestione della memoria.Invece, sviluppare una politica di caching efficace per la gestione degli oggetti dell'applicazione.

Ovviamente è possibile ignorare quella linea guida e lavorare efficacemente il codice per renderlo conto.

È possibile implementare la politica di memorizzazione nella cache e al termine del salvataggio nel database, sul recupero e sulla cache. Utilizzare una scadenza scorrevole ovviamente poiché si è interessati a mantenere quelli più usati.

Ricordare tuttavia che il più usato e il più pesante è un compromesso. Perdere un oggetto 10 volte al giorno che impiega 5 minuti per ripristinare infastidirebbe gli utenti molto più che perdere un oggetto 10000 volte lo strumento a soli 5 ms da ripristinare.

E qualcuno sopra menzionato la cache web. Fa la gestione automatica della memoria con le richiamate come indicato, dipende se si vuole trascinarlo nelle proprie app.

E ... ultimo ma non meno importante, guarda una cache distribuita. Con il sharding puoi dividere quel grande dizionario su poche macchine.

Problemi correlati