Очень большая коллекция в .NET вызывает исключение вне памяти

StackOverflow https://stackoverflow.com/questions/3657181

Вопрос

Я проверяю, насколько большая коллекция может быть в .NET. Технически любой объект коллекции может вырастеть размеру физической памяти.

Затем я протестировал следующий код в SEVER, который имеет 16 ГБ памяти, запустив Windows 2003 Server и Visual Studio 2008. Я протестировал как F #, так и C # код и посмотрел на диспетчер задач во время работы. Я вижу, что после растущей памяти 2 ГБ программа разбилась с исключением вне памяти. Я установил целевую платформу на X64 на странице свойств.

open System.Collections.Generic

let d = new Dictionary<int, int>()

for i=1 to 1000000000 do
    d.Add(i,i)

Я сделал тот же тест на C5. Библиотека коллекции. Результатом является то, что словарь в C5 может использовать всю память. Код использует C5:

let d = C5.HashDictionary<int, int> ()
for i=1 to 1000000000 do
    d.Add(i,i)

Кто-нибудь знает почему?

Это было полезно?

Решение

Microsoft CLR имеет ограничение максимального размера объекта 2 ГБ, даже 64-битная версия. (Я не уверен, также присутствует ли этот предел в других реализациях, таких как моно.)

Ограничение относится к каждому Один Объект - не общий размер всех объектов - что означает, что это относительно легко обходятся с использованием композитной коллекции некоторых сортов.

Есть обсуждение и какой-то пример код здесь ...

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

При запуске 64-битного управляемого приложения на 64-битной операционной системе Windows вы можете создать объект не более 2 гигабайт (GB).

Другие советы

В версиях .NET до 4.5 максимальный размер объекта составляет 2 ГБ. С 4,5 назад вы можете выделить большие объекты, если gcallowverylargeObjects. включен. Обратите внимание, что предел для string Не затрагивается, но «массивы» должны охватывать «списки» тоже, поскольку списки поддерживаются массивами.

И чтобы быть понятным, словарь использует один массив для добавления пар. Он выращивается (удвоился?) Каждый раз, когда он полон. Когда есть 512 миллионов объектов, его размер составляет 2 Гбайте (с 32-битным указателем объекта, и предполагая идеальное распределение). Добавление еще одного элемента делает словарь снова удвоить размер массива снова. Бум.

HASHDICTIRY C5 использует линейное перемешивание и, вероятно, использует массив ведерных ведерных элементов, содержащих несколько (16?) Элементов. Это должно столкнуться с той же проблемой (много) позже.

«Разрешить крупные объекты» поможет только избавиться от исключения OOM.

Когда нужно будет хранить очень много объектов, проблема, которую вы увидите, это стойлы GC (паузы). То, что мы сделали, это «скрытие» данных из GC, которая превратилась в очень практическое решение.

Видеть это: https://www.infoq.com/articles/big-memory-part-3.

Вы можете использовать кеш, который работает как словарь:https://github.com/aumcode/nfx/tree/master/source/nfx/aplicationModel/pile.

Смотрите сечение кэширования

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top