Как определить максимальное значение параметра емкости, передаваемого в конструктор Dictionary, чтобы избежать исключения OutOfMemoryException?

С этим связано:

System.OutOfMemoryException из-за большого словаря

я получаю OutOfMemoryException когда я позволю.NET управлять моим словарем. Исключение, выброшенное в методе изменения размера. Поэтому я пытался избежать изменения размера, предоставляя большое количество в качестве емкости. Естественно я пытался начать с int.MaxValue просто чтобы убедиться, что это поможет решить проблему. Я планировал идти вниз столько, сколько нужно.

тем не мение OutOfMemoryException брошен для int.MaxValue, Я решил сделать небольшой двоичный поиск, и самое первое значение для емкости, которое было принято конструктором, оказалось int.MaxValue / 32, Мало того, что это меньше, чем я ожидал, но это также просто сбивает с толку.

Так у кого-нибудь есть идеи почему?

О, настройки проекта настроены на использование архитектуры x64.

2 ответа

Решение

Жесткий предел для Dictionary<TKey, TValue> из-за частного поля entries, который имеет тип Entry[], В этом случае Entry это структура:

private struct Entry {
  public int hashCode;
  public int next;
  public TKey key;
  public TValue value;
}

Минимальный размер Entry 4*4, что может произойти, если TKey а также TValue оба являются 4-байтовыми типами (ссылаются на размер выравнивания массива, то есть значение, возвращаемое CLI sizeof инструкция байт-кода). Это приводит к ограничениюint.MaxValue / (2*16)записи из-за ограничения размера массива в.NET. Если вы используетеTKeyили жеTValueтип, который больше чем 4 байта, максимальный размер словаря уменьшился бы соответственно.

Для больших словарей, как вы предлагаете, реализация дерева B+IDictionary<TKey, TValue> будет более эффективным использованием системных ресурсов и не будет подвергаться ограничению размера массива.

Просто чтобы добавить к ответу 280Z28:

Если вам действительно нужен такой большой словарь, и вы работаете на x64, и используете.Net 4.5 или новее, тогда вы можете включить поддержку больших объектов. Это позволит гораздо больший словарь.

В моих тестах я мог указать емкость до int.MaxValue/2

Для этого добавьте в свой файл app.config следующий раздел:

<runtime>
  <gcAllowVeryLargeObjects enabled="true" />
</runtime>

Таким образом, весь ваш файл app.config может выглядеть так:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
    </startup>
  <runtime>
    <gcAllowVeryLargeObjects enabled="true" />
  </runtime>
</configuration>

Смотрите здесь для получения более подробной информации: http://msdn.microsoft.com/en-us/library/hh285054.aspx

Другие вопросы по тегам