2013-08-26 3 views
3

Я загружаю данные csv из файлов в datatable для обработки.Огромное потребление памяти DataTable

Проблема заключается в том, что я хочу обрабатывать несколько файлов, а мои тесты с помощью datatable показывают мне огромное потребление памяти. Я тестировал файл csv размером 37 МБ, а память выросла до 240 МБ, что является способом для многих ИМХО. Я читал, что в datatable есть накладные расходы, и я мог бы жить с размером около 70 МБ, но не 240 МБ, а это значит, что он в шесть раз превышает первоначальный размер. Я читаю здесь, что для данных данных требуется больше памяти, чем POCOs, но разница слишком велика.

Я надел профайлер памяти и посмотрел, если у меня есть утечки памяти и где находится память. Я обнаружил, что у datatablecolumns между 6MB и 19MB, заполненными строками, и у datatable было около 20 столбцов. Значения хранятся в столбцах? Почему так много памяти, что я могу сделать, чтобы уменьшить потребление памяти. С этими потребляемыми в памяти расходными материалами кажется непригодным.

Были ли у кого-то еще такие проблемы с datatables, или я что-то не так?

PS: Я пробовал файл размером 70 МБ, а число данных увеличивалось до 500 МБ!

OK Вот небольшая тестовая таблица: 37-мегабайтный csv-файл (21 колонка) позволяет памяти расти до 179 МБ.

private static DataTable ReadCsv() 
    { 
     DataTable table = new DataTable(); 
     table.BeginLoadData(); 

     using (var reader = new StreamReader(File.OpenRead(@"C:\Develop\Tests\csv-Data\testdaten\test.csv"))) 
     {    
      int y = 0; 
      int columnsCount = 0; 
      while (!reader.EndOfStream) 
      { 
       var line = reader.ReadLine(); 
       var values = line.Split(','); 

       if (y == 0) 
       { 
        columnsCount = values.Count(); 
        // create columns 
        for (int x = 0; x < columnsCount; x++) 
        { 
         table.Columns.Add(new DataColumn(values[x], typeof(string))); 
        } 
       } 
       else 
       { 
        if (values.Length == columnsCount) 
        { 
         // add the data 
         table.Rows.Add(values); 
        } 
       } 

       y++; 
      } 

      table.EndLoadData(); 
      table.AcceptChanges(); 

     } 

     return table; 
    } 
+0

Вы хотите, чтобы мы догадались или вы покажете нам какой-то код? – Ehsan

+0

Я предполагаю, что в вашем коде должны быть какие-то другие объекты? –

+1

Память дешевая, но: Возможно, это поможет найти более эффективное решение для памяти: http://stackoverflow.com/questions/275269/does-a-datatable-consume-more-memory-than-a-listt – dcaswell

ответ

0

DataTables - это общее решение по размещению табличных данных в памяти и добавление множества связанных с таблицами функций. Если накладные расходы неприемлемы, у вас есть возможность: 1) написать свой собственный класс DataTable, который устраняет накладные расходы, которые вам не нужны. 2) Используйте альтернативное представление, которое все еще выполняет то, что вам нужно, возможно, на основе POCO или, возможно, XMLDocument (Может быть, столько же накладных расходов, может быть, больше, никогда не беспокоиться об этом). 3) Остановите попытку загрузить все в память и просто принесите данные по мере необходимости из своего внешнего хранилища.

+0

1 Alread попробовал Silverlight datatable от Telerik (http://blogs.telerik.com/vladimirenchev/posts/09-04-23/lightweight-datatable-for-your-silverlight-applications.aspx), это НЕ легкий, он потребляет гораздо больше памяти. Проблема в том, что если вы хотите, чтобы возможности редактирования не были легкими. В противном случае использование словаря будет более легким, это моя единственная надежда. – JohnnyBravo75

+0

2. POCO не является альтернативой, потому что у меня нет специальных данных. Каждая информация имеет другую структуру. 3. Да, это то, что я оцениваю. Проблема в том, что мне нужно обрабатывать данные, строить ключевые столбцы/индексы, сортировать их ... Возможно, легкая база данных, такая как sqlite, - это путь. – JohnnyBravo75

+0

Это очень похоже на мой вариант 3 - Есть несколько вариантов базы данных. Легкий вес может быть хорошим выбором, или вам может понадобиться что-то более масштабируемое, но Базы данных в значительной степени являются одной из первых вещей, которые вы должны использовать, когда ваша информация не подходит удобно в память или когда вам нужен постоянный магазин. Это то, что они делают. Если вы сейчас внесете изменения, то вверх - это то, что по мере того, как вы продолжаете добавлять данные, вы не просто вдруг «попадете в стену» –

1

DataSet и его дети DataTable, DataRow и т. Д. Составляют реляционную базу данных в памяти. Существует много накладных расходы (хотя это делает [некоторые] вещи очень удобно.

Если память является проблемой,

  • Построить домен объектов представлять каждую строку в вашем CSV-файл с машинописным . свойства
  • Создание пользовательской коллекции (или просто использовать IList<T> держать их
  • Кроме того, построить класс облегченного с основной семантикой DataTable:
    • возможность выбора строки по номеру
    • возможность выбора столбца в строке по номеру строки и имени или номеру столбца.
    • Способность знать упорядоченный набор имен столбцов
    • Бонус: Возможность выбора столбца по имени или порядковому номеру и получить список его значений, по одному в каждой строке.

Вы уверены, что вам нужно представление в памяти файлов CSV? Не могли бы вы получить к ним доступ через IDataReader, как и у Себастьяна Лориона Fast CSV Reader?

+0

Да, но фактора 6-7 быть не может. В моем коде должна быть проблема, иначе данные datatables являются непригодными для использования. Вот почему я попросил сравнить статистические/опытные ценности с другими пользователями. Никакая база данных не имеет таких накладных расходов. Если я помещу их в Sqlite, он не станет таким большим. Я написал свой собственный csv reader, AdoAdapter, XmlReader и разработал приложение для работы с datables в памяти, и с вычислением второго фактора он будет работать. Но это накладные расходы разрушит мой дизайн. Каков опыт других пользователей? – JohnnyBravo75

Смежные вопросы