Strategia per la memorizzazione di valori misti e tipi di riferimento senza box

1

Sto cercando un modo per memorizzare una grande quantità di valori di dati individuali, con i seguenti vincoli.

  • Supponiamo che i tipi siano bool, int32, double, decimal, string e blob (array di byte).
  • Il tipo di ciascun valore non sarà noto al momento della compilazione (ma l'insieme di possibili tipi è).
  • Il tipo di ciascun valore sarà noto in fase di esecuzione, quindi non bisogno di per conoscere il proprio tipo.
  • Ce ne sono molti - pensa almeno a milioni.
  • I valori vengono raccolti in righe / buste di (diciamo) valori 1-100 e accessibili per indice (da un dizionario come accade).
  • I valori vengono creati e distrutti a volte, letti spesso e aggiornati raramente.

Le strategie che ho finora sono solo queste:

  • Matrice di oggetti, ma richiederebbe che i tipi di valore siano racchiusi in una scatola e questo è un carico sul GC che preferirei evitare.
  • Serializza su un flusso di byte. String e blob richiederebbero una lunghezza incorporata. Il costo di lettura / aggiornamento è elevato.

In C ++ questa potrebbe essere una matrice di unione di tipi di puntatori e scalari, ma tale strategia non è disponibile (o almeno molto pericolosa) in .NET. Questo è un luogo in cui davvero non ho bisogno di un GC (la distruzione degli oggetti è deterministica), quindi chiamare fuori codice non gestito è una possibilità.

La domanda è se mi sono perso strategie praticabili nel mondo .NET. Suggerimenti / commenti benvenuti.

Per la mia particolare applicazione sembra che la creazione / cancellazione avvenga in lotti (righe / sacchetti / serie) e che i singoli valori non vengano aggiunti o cancellati. Pensa a serializzazione / deserializzazione piuttosto che a un accesso casuale. Ci sono anche operazioni impostate, quindi value-compare-equals è un'operazione comune e la boxe non è buona.

    
posta david.pfx 19.09.2014 - 05:28
fonte

1 risposta

1

Creerei un array strongmente tipizzato per ogni tipo di valore e useremo ogni array come un pool di potenziali value holders. Un'altra opzione, leggermente più lenta, consiste nell'utilizzare un set di List in cui ogni istanza di List contiene tipi di valori diversi.

Questo è simile alla strategia di raggruppamento comunemente usata per l'ottimizzazione dell'allocazione della memoria. A List, o il tuo array, dovrà espandersi a volte. In questo caso, è necessario assegnare un nuovo array e copiare i vecchi contenuti su quello nuovo.

Sia che si utilizzi List o un array, in entrambi i casi si evita completamente la boxe e si utilizza la memoria nel modo più efficiente possibile nel CLR. L'indice di un elemento nel pool è composto da: il tipo (per sapere a quale elenco o array accedere) e l'array o l'indice di elenco. L'unica altra ottimizzazione che riesco a pensare è consolidare i tipi laddove possibile: UInt32 e Int32 possono condividere lo stesso contenitore, ad esempio.

Fai attenzione al pugilato quando scrivi i metodi che memorizzano o recuperano i valori. Avrai bisogno di argomenti strongmente tipizzati.

Gli oggetti di dimensioni variabili, come gli array di byte, sono archiviati in modo efficiente in un flusso. Tuttavia, per utilizzare l'oggetto memorizzato come array di byte, è necessario assegnarne uno nuovo e copiare parte dello stream nel nuovo array. È più efficiente riutilizzare gli array allocati in precedenza.

    
risposta data 19.09.2014 - 18:25
fonte

Leggi altre domande sui tag