Как определить максимальное значение параметра емкости, передаваемого в конструктор 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