Очень большая коллекция в .Net вызывает исключение нехватки памяти - PullRequest
32 голосов
/ 07 сентября 2010

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

Затем я протестировал следующий код на сервере, который имеет 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)

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

Ответы [ 4 ]

42 голосов
/ 07 сентября 2010

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

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

Здесь есть обсуждение и пример кода ...

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

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

21 голосов
/ 26 июня 2012

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

11 голосов
/ 13 октября 2010

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

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

1 голос
/ 16 июля 2017

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

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

Смотрите это: https://www.infoq.com/articles/Big-Memory-Part-3

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

см. Раздел кэширования

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...