System.OutOfMemoryException из-за большого словаря
Я держу большой кеш в словаре со значением IEnumerable<KeyValuePair<DateTime, Double>>
, Я периодически удаляю элементы из словаря и периодически добавляю их в словарь. Время от времени я получаю System.OutOfMemoryException. Я хотел знать, почему сборщик мусора не приходит мне на помощь?
4 ответа
Помните, что куча может быть фрагментирована, как упоминалось @Gabe. Несмотря на то, что у вас может быть свободная память, у него может не быть достаточно большого куска для размещения словаря, когда он выполняет его изменение размера.
Возможно, вы могли бы использовать блок кэширования из библиотеки MSDN Library Link, который поможет вам реализовать хороший кеш. Может быть, вы могли бы выбрать алгоритм, который не распределяет память динамически, с фиксированным количеством записей?
Также обратите внимание, что если нет памяти, которую вы можете использовать, то это проблема с размером вашего кэша, а не сборщика мусора.
Вполне возможно, что GC приходит вам на помощь в течение длительного времени, но иногда вы просто выходите за пределы его возможностей.
Просто чтобы быть абсолютно ясным, это Dictionary<DateTime, Double>
или Dictionary<SomeKeyType, IEnumerable<KeyValuePair<DateTime, Double>>>
? Если это последнее, то, возможно, вы держите ссылки в другом месте?
Насколько велик ваш кеш? У вас есть мониторинг, чтобы отслеживать это? Что заставляет вас думать, что именно словарь вызывает проблему? Если у вас есть контроль над объемом кеша, вы пытались уменьшить размер?
Поскольку вы спрашиваете, почему GC не спасает вас, я отвечу на это.
Использование языка программирования / среды с сборщиком мусора облегчит вам жизнь, но не уйдет в прошлое.
Если вы назначаете большой кусок памяти, превышающий 2 гигабайта на 32-битной машине xp, вы только что достигли одной из первых границ памяти.Net. Держать 2 гигабайта в памяти всегда плохая идея.
На машине с ограниченным объемом памяти, работающей с огромной базой данных и т. П., Вы быстро выйдете за границы доступной памяти. Поскольку GC не осведомлен об ОС, он может заметить, что во времени наблюдается нехватка памяти (создание огромных объектов, таких как растровые изображения, может вызвать эту ситуацию). Вызов GC.Collect вручную, когда вы установили огромный объект, ничем не помогал.
Хранение большого словаря в памяти - очень простое описание. Можете ли вы рассказать нам, что в коллекции и насколько эти предметы теоретически большие.
Если вы имеете в виду большие, как 2 147 483 647 предметов, вы могли бы достичь предела целочисленного размера.
Подводить итоги:
- Не храните ненужные элементы в памяти и не удаляйте их на диск.
- Вызывайте GC.Collect, как только вы освободите "большие" элементы (но не в цикле удаления элементов, пожалуйста, после цикла)
Я не уверен, извините, если я ошибаюсь, но, возможно, словарь хранится в куче больших объектов, когда его размер превышает 85 КБ (например, байт [90000])
Как Гейб Саид:
Я вижу, что, возможно, куча больших объектов фрагментируется, и вы не сможете увеличить словарь после точки
Когда LOH фрагментируется, у него иногда не хватает места для сохранения объекта с постоянным адресом. Вот что вызывает исключение OutOfMemory. Это больше похоже на пространство Out Of Contigus в исключении LOH.