Нормальный ли размер моего словаря? - PullRequest
4 голосов
/ 09 ноября 2011

У меня есть файл 150 МБ.Каждая строка состоит из одного и того же формата, например, /

I,h,q,q,3,A,5,Q,3,[,5,Q,8,c,3,N,3,E,4,F,4,g,4,I,V,9000,0000001-100,G9999999990001800000000000001,G9999999990000001100PDNELKKMMCNELRQNWJ010, , , , , , ,D,Z,

У меня есть Dictionary<string, List<string>>

Заполняется путем открытия файла, чтения каждой строки, взятия элементов из строки идобавив его в словарь, файл закрывается.

StreamReader s = File.OpenText(file);
 string lineData = null;
 while ((lineData = s.ReadLine()) != null)
 {
   var elements = lineData.Split(',');
   var compareElements = elements.Take(24);
   FileData.Add(elements[27], new List<string>(compareElements));

  }
  s.Close();

Используя метод, приведенный в этом ответе Я рассчитал, что мой словарь равен 600 МБ.Это в 4 раза больше, чем файл.

Это звучит правильно?

Ответы [ 6 ]

3 голосов
/ 09 ноября 2011

Помимо того, что метод не очень надежен, в вашем случае есть еще большие накладные расходы.Вы заметили, что каждая итерация вашего цикла создает новый экземпляр массива elements, строку lineData, и elements.Take также имеет некоторые внутренние переменные, которые создаются при каждом вызове?Поскольку у вас, вероятно, достаточно ОЗУ, сборщик мусора .NET не утруждает себя их сборкой, поэтому, когда вы измеряете TotalMemory до и после цикла, вы также измеряете все эти переменные, а не только свой словарь, хотя это может быть единственной вещьюэто остается в поле зрения впоследствии.

1 голос
/ 09 ноября 2011

Если ваш файл закодирован в ANSI или UTF-8 (, но без специальных символов, тогда размер такой же, как ANSI) (каждый символ 1 байт) и string - "Представляеттекст в виде последовательности символов Unicode. " (Unicode = UTF-16, каждый символ 4 байта), это в 4 раза больше.

1 голос
/ 09 ноября 2011

Большинство этих объектов принимают только один символ, но вы храните их как строки. Ссылочный указатель на эти строки в одиночку займет как минимум в два раза больше места (в случае UTF8, вероятно, в 4-8 раз больше). Кроме того, возникает необходимость сохранить структуру хэш-таблицы для словаря.

List<> сам по себе должен быть действительно эффективным хранилищем (он использует массив внутри)

Комната для улучшения :

  • вы можете использовать List<char> или char[] вместо List<string>, если вы знаете, что поля будут соответствовать
  • вы можете использовать struct Field { char a,b/*,...*/; } и List вместо List, если вам нужно более 1 символа на поле
  • Вы можете отказаться от активного извлечения поля [<- рекомендуется]: </p>

     var dict = File.ReadAllLines(file)
          .ToDictionary(line => line.Split(',')[27]);
    

    Это дает вам возможность получить доступ к элементам сравнения по запросу:

     string[] compareElements = dicts["key27"].Split(',')/*.Take(24).ToArray()*/;
    

    Это классический пример компромисса между временем выполнения и стоимостью хранения

Редактировать очевидный гибрид будет:

struct AllCompareElements
{
     public char field1, field2, ... field24;
     // perhaps:
     public char[2] field13; // for the exceptional field that is longer than 1 character
}

Счастливо использовать Resharper для реализации Equals, GetHashCode, IEquatable<AllCompareElements>, IComparable<AllCompareElements>

1 голос
/ 09 ноября 2011

Я предполагаю, что ваш файл имеет кодировку UTF-8 и содержит в основном ASCII.Строки в C # - это UTF-16, поэтому это объясняет большую часть различий в размерах (в 2 раза).Конечно, есть некоторые накладные расходы для структур данных.

1 голос
/ 09 ноября 2011

Да, потому что вы превращаете символы в строковые указатели, каждый по 4 или 8 байтов.

0 голосов
/ 09 ноября 2011

Это 600M было выделено операцией загрузки файла в словарь ... Предполагается, что это дорогостоящая операция, и она может быть полезна для определения эффективности любой оптимизации, но сколько памяти занимает словарь,довольно бесполезно.

Я бы отложил расщепление, как сразу предложил Сехе.

Мне кажется, что вы заранее оптимизировали скорость и это стоило вам большого стиля на отпечаток памяти.

...