2011-09-14 20 views
7

Ho bisogno di eseguire le operazioni in ordine cronologico su enormi serie temporali implementate come IList. I dati vengono infine archiviati in un database, ma non avrebbe senso inviare decine di milioni di query al database.Implementazione IList di file mappati in memoria, per la memorizzazione di serie di dati di grandi dimensioni "in memoria"?

Attualmente IList in memoria attiva un'eccezione OutOfMemory quando si tenta di archiviare più di 8 milioni (piccoli) oggetti, anche se dovrei occuparmi di decine di milioni.

Dopo alcune ricerche, sembra che il modo migliore per farlo sarebbe quello di memorizzare i dati su disco e accedervi tramite un wrapper IList.

Memory-mapped files (introdotto in .NET 4.0) sembra l'interfaccia corretta da utilizzare, ma mi chiedo quale sia il modo migliore per scrivere una classe che dovrebbe implementare IList (per un facile accesso) e gestire internamente un file mappato in memoria.

Sono anche curioso di sapere se conosci altri modi! Ho pensato ad esempio a un wrapper IList che utilizzava dati da db4o (someone mentionned here usando un file mappato in memoria come IoAdapterFile, sebbene l'uso di db4o probabilmente aggiunga un costo delle prestazioni rispetto a quello diretto con il file mappato in memoria).

Mi sono imbattuto nel this question chiesto nel 2009, ma non ha prodotto risposte utili o idee serie.

+0

sono le operazioni che esegui in sequenza? o stai operando sull'intero dato tutto in una volta? – Yahia

+0

L'accesso deve essere sequenziale (iterando sulla raccolta per eseguire un aggiornamento) e devo anche essere in grado di eliminare/rimuovere oggetti all'estremità. –

+2

Un database è lo strumento giusto per questo lavoro. Aggiorna i dati in batch per evitare troppe chiamate al database. Potresti anche essere interessato all'elaborazione dello stile per ridurre le mappe per accelerare un po 'le cose. – dtb

risposta

8

Ho trovato questo PersistentDictionary<>, ma funziona solo con le stringhe e leggendo il codice sorgente non sono sicuro che sia stato progettato per dataset di grandi dimensioni.

Più scalabile (fino a 16 TB), il ESENT PersistentDictionary<>, utilizza il motore di database ESENT presente in Windows (XP +) e può archiviare tutti gli oggetti serializzabili contenenti tipi semplici.

Disk Based Data Structures, including Dictionary, List and Array with an "intelligent" serializer sembrava esattamente come quello che stavo cercando, ma non ha funzionato senza problemi con dataset estremamente grandi, soprattutto perché non fa uso dei "MemoryMappedFiles" nativi .NET ancora, e il supporto per i sistemi a 32 bit è sperimentale .

Aggiornamento 1: Ho finito per implementare la mia versione che fa largo uso di .NET MemoryMappedFiles; è molto veloce e probabilmente lo rilascerò su Codeplex dopo averlo reso migliore per usi più generici.

Aggiornamento 2: TeaFiles.Net ha funzionato perfettamente per il mio scopo. Altamente raccomandato (e gratuito).

+0

Grazie per aver condiviso le tue esperienze. Mi sto imbattendo nello stesso problema e mi stavo chiedendo se hai già pubblicato la tua implementazione su Codeplex o no. Grazie. – alhazen

+0

Ciao, non ancora. Un vincolo che attualmente ho è che tutti gli oggetti da memorizzare devono essere di tipi di valore. Se questo è il tuo caso (o puoi migrare dal tipo di riferimento ai tipi di valore), allora posso condividere il mio codice con te prima di pubblicare su Codeplex. –

+0

@ErwinMayer Mi chiedo se hai condiviso il codice da qualche parte. Ho bisogno di un'implementazione di IList supportata da file per alcuni oggetti di grandi dimensioni. –

1

I file mappati in memoria sono un bel modo per farlo. Ma sarà molto lento se devi accedere alle cose in modo casuale.

La soluzione migliore è probabilmente quella di creare una dimensione di struttura fissa se salvata in memoria (se possibile), quindi utilizzare l'offset come ID di elemento di elenco. Tuttavia, l'eliminazione/l'ordinamento è sempre un problema.

+0

AFAIK, l'accesso casuale deve essere O (1), dato che conosciamo l'offset di byte. –

3

vedo diverse opzioni:

  • "in-memory-DB"
    ad esempio SQLite può essere usato in questo modo - non necessita di alcuna installazione, ecc basta distribuire la DLL (1 o 2) insieme con l'app e il resto può essere fatto a livello di programmazione
  • Caricare tutti i dati in tabelle temporanee nel DB, con quantità di dati sconosciute (ma grandi) ho trovato che questo si ripaga molto velocemente (e l'elaborazione può essere eseguita normalmente all'interno del DB che è ancora meglio!)
  • utilizzare un file mappato in memoria e una dimensione struttura fissa (accesso array come tramite offset) ma attenzione che la memoria fisica è il limite tranne si utilizza una sorta di "finestra scorrevole" per mappare solo alcune parti in memoria
Problemi correlati