Подтвердить что ты не робот

Каковы издержки памяти для хранения данных в .NET DataTable?

Я пытаюсь получить дескриптор объема служебных данных памяти, связанных с .NET DataTable, и с отдельными DataRows в таблице.
Другими словами, сколько памяти занимает таблица данных, чем то, что нужно просто для хранения правильно типизированного массива каждого столбца данных?
Я предполагаю, что будут некоторые основные накладные расходы на таблицу, плюс некоторая сумма за столбец, а затем снова дополнительная сумма за строку.

Так может ли кто-нибудь дать оценку (и, я думаю, объяснение!) каждого/любого из этих трех видов накладных расходов?

4b9b3361

Ответ 1

Ну, не забывайте, что DataTable хранит 2? 3? версии данных - оригинальные и обновленные (возможно, другие?). Он также имеет множество ссылок, поскольку он основан на ячейках и бокс для любых типов значений. Было бы сложно определить точную память...

Лично я редко использую DataTable - типичные классы POCO - гораздо более разумная ставка, на мой взгляд. Я бы не использовал массив (напрямую), хотя - List<T> или BindingList<T> или подобное было бы гораздо более распространенным.

В качестве грубой меры вы можете создать множество таблиц и т.д. и посмотреть на использование памяти; например, следующее показывает коэффициент ~ 4.3, то есть более чем в 4 раза дороже, но, очевидно, это сильно зависит от количества столбцов против строк и таблиц и т.д.:

    // 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();

против

    // 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();

(на основе)

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; }
}

Ответ 2

Накладные расходы довольно низки, если вы не определяете индексы столбцов. Вы можете получить довольно низкий объем памяти, если вы используете кеширование строк: Используйте HashSet или Dictionary, чтобы использовать только один экземпляр строки для каждого строкового значения. Это звучит странно, но если вы извлекаете данные из базы данных и имеете несколько строк с тем же строковым значением (например, "ALFKI" ), то строковые значения равны, но экземпляры строк не являются: строка хранится несколько раз в Память. Если вы сначала используете HashSet для фильтрации повторяющихся экземпляров, вы эффективно используете один и тот же экземпляр строки для 1 строкового значения всюду в вашем datatable. Это может значительно уменьшить объем памяти. Конечно, если значения строк уже статически определены где-то (поэтому не читаются из внешнего источника), это не стоит усилий.

Ответ 3

Это зависит от того, сколько данных и каких данных вы храните. Очевидно, чем больше данных, тем больше памяти. Есть некоторые накладные расходы, связанные с datatable, что делает его немного дороже. Вы также должны знать о кучи больших объектов. Если вы храните объекты более 85 кб, объект будет храниться в LOH. Это может нанести ущерб вашей сборке мусора, поскольку для этого требуется полная сборка. Если вы хотите проверить его, загляните в профайлер памяти, чтобы наблюдать за памятью данных в формате datatable.