Qual è il sovraccarico di memoria derivante dall'archiviazione dei dati in un DataTable .NET?

StackOverflow https://stackoverflow.com/questions/424598

Domanda

Sto cercando di ottenere un controllo sulla quantità di sovraccarico di memoria associato a un DataTable .NET e ai singoli DataRow all'interno di una tabella.
In altre parole, quanta memoria occupa una tabella di dati in più rispetto a quella necessaria semplicemente per memorizzare un array tipizzato correttamente di ciascuna colonna di dati?
Immagino che ci sarà un sovraccarico di base della tabella, più un certo importo per colonna e poi ancora un importo aggiuntivo per riga.

Qualcuno può quindi fornire una stima (e, immagino, una spiegazione!) di ciascuno/qualcuno di questi tre tipi di spese generali?

È stato utile?

Soluzione

Bene, non dimenticare che a DataTable negozi 2?3?versioni dei dati: originali e aggiornate (forse un'altra?).Ha anche molti riferimenti poiché è basato su celle, e boxing per qualsiasi tipo di valore.Sarebbe difficile quantificare la memoria esatta...

Personalmente lo uso molto raramente DataTable - Le classi POCO digitate sono una scommessa molto più sensata a mio avviso.Tuttavia, non utilizzerei un array (direttamente) - List<T> O BindingList<T> o simili sarebbero molto più comuni.

Come misura approssimativa, potresti creare molte tabelle ecc. E osservare l'utilizzo della memoria;ad esempio, quanto segue mostra un fattore ~4,3, ovveropiù di 4 volte più costoso, ma ovviamente dipende molto dal numero di colonne, righe, tabelle, ecc.:

    // takes **roughly** 112Mb  (taskman)
    List<DataTable> tables = new List<DataTable>();
    for (int j = 0; j < 5000; j++)
    {
        DataTable table = new DataTable("foo");
        for (int i = 0; i < 10; i++)
        {
            table.Columns.Add("Col " + i, i % 2 == 0 ? typeof(int)
                                : typeof(string));
        }
        for (int i = 0; i < 100; i++)
        {
            table.Rows.Add(i, "a", i, "b", i, "c", i, "d", i, "e");
        }
        tables.Add(table);
    }
    Console.WriteLine("done");
    Console.ReadLine();

contro

    // takes **roughly** 26Mb (taskman)
    List<List<Foo>> lists = new List<List<Foo>>(5000);
    for (int j = 0; j < 5000; j++)
    {
        List<Foo> list = new List<Foo>(100);
        for (int i = 0; i < 100; i++)
        {
            Foo foo = new Foo { Prop1 = "a", Prop3 = "b",
                 Prop5 = "c", Prop7 = "d", Prop9 = "e"};
            foo.Prop0 = foo.Prop2 = foo.Prop4 = foo.Prop6 = foo.Prop8 = i;
            list.Add(foo);
        }
        lists.Add(list);
    }
    Console.WriteLine("done");
    Console.ReadLine();

(basato su)

class Foo
{
    public int Prop0 { get; set; }
    public string Prop1 { get; set; }
    public int Prop2 { get; set; }
    public string Prop3 { get; set; }
    public int Prop4 { get; set; }
    public string Prop5 { get; set; }
    public int Prop6 { get; set; }
    public string Prop7 { get; set; }
    public int Prop8 { get; set; }
    public string Prop9 { get; set; }
}

Altri suggerimenti

Il sovraccarico è piuttosto basso se non si definiscono gli indici sulle colonne. È possibile ottenere un footprint di memoria piuttosto basso se si utilizza la memorizzazione nella cache di stringhe: Utilizzare un HashSet o un dizionario per utilizzare solo 1 istanza di stringa di ogni valore di stringa. Sembra strano, ma se si recuperano dati da un database e si hanno più righe con lo stesso valore di stringa (ad es. & Quot; ALFKI & Quot;), i valori di stringa sono uguali, ma le istanze di stringa non lo sono : la stringa viene archiviata più volte in memoria. Se si utilizza per la prima volta un HashSet per filtrare le istanze duplicate, si utilizza effettivamente la stessa istanza di stringa per 1 valore di stringa ovunque nel proprio datatable. Ciò può ridurre notevolmente l'ingombro della memoria. Naturalmente, se i valori delle stringhe sono già definiti staticamente da qualche parte (quindi non letti da una fonte esterna), non vale la pena.

Dipende dalla quantità di dati e dal tipo di dati che stai memorizzando. Ovviamente più dati, più memoria. C'è un sovraccarico associato al datatable che lo rende un po 'più costoso. È inoltre necessario conoscere l'heap di oggetti di grandi dimensioni. Se si memorizzano oggetti oltre 85 kb, l'oggetto verrà memorizzato nel LOH. Questo può provocare il caos nella tua raccolta dei rifiuti in quanto richiede una raccolta completa. Se sei pronto per testarlo, cerca in un profiler di memoria per vedere il footprint di memoria del datatable.

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