System.OutOfMemoryException из-за большого словаря - PullRequest
5 голосов
/ 17 марта 2011

Я храню большой кеш в словаре со значением IEnumerable<KeyValuePair<DateTime, Double>>. Я периодически удаляю элементы из словаря и периодически добавляю их в словарь. Время от времени я получаю System.OutOfMemoryException. Я хотел знать, почему сборщик мусора не приходит мне на помощь?

Ответы [ 4 ]

3 голосов
/ 17 марта 2011

Помните, что куча может быть фрагментирована, как упомянуто @Gabe. Несмотря на то, что у вас может быть свободная память, у него может не хватить фрагмента, достаточного для выделения словаря при его изменении.

Возможно, вы могли бы использовать блок кэширования из библиотеки шаблонов и практик Ссылка на библиотеку MSDN , которая поможет вам реализовать хороший кэш. Может быть, вы могли бы выбрать алгоритм, который не распределяет память динамически, с фиксированным числом записей?

Также обратите внимание, что если нет памяти, которую вы можете использовать, то это проблема с размером вашего кэша, а не сборщика мусора.

2 голосов
/ 17 марта 2011

Поскольку вы спрашиваете, почему GC не спасает вас, я отвечу на это.

Использование языка программирования / среды с сборщиком мусора облегчает вам жизнь, но не даетсделать управление памятью ушедшим в прошлое.

Если вы назначаете большой кусок памяти, превышающий 2 гигабайта на 32-битной машине xp, вы только что достигли одной из первых границ памяти .Net.Оставлять 2 гигабайта в памяти - это всегда плохая идея.

На машине с ограниченным объемом памяти, работающей с огромной базой данных или чем-то подобным, вы быстро выйдете за границы доступной памяти.Так как GC не знает ОС, он может заметить, что со временем возникает нехватка памяти (создание огромных объектов, таких как растровые изображения, может вызвать эту ситуацию).Ручной вызов GC.Collect, когда вы установили огромный объект, ничем не поможет.

Хранение большого словаря в памяти - очень простое описание.Можете ли вы рассказать нам, что в коллекции и насколько эти предметы теоретически большие.

Если вы имеете в виду большие, как 2 147 483 647 предметов, вы можете достичь предела целочисленного размера.

Подводя итог:

  • Не оставляйте ненужные элементы в памяти илипоменять их на диск.
  • Звоните в GC. Соберите, как только вы освободите «большие» элементы (но не в цикле удаления элементов, после цикла, пожалуйста)
2 голосов
/ 17 марта 2011

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

Просто чтобы быть абсолютно ясным, это Dictionary<DateTime, Double> или Dictionary<SomeKeyType, IEnumerable<KeyValuePair<DateTime, Double>>>? Если это последнее, то, возможно, вы держите ссылки в другом месте?

Насколько велик ваш кеш? У вас есть мониторинг, чтобы отслеживать это? Что заставляет вас думать, что именно словарь вызывает проблему? Если вы контролируете объем кеша, пытались ли вы уменьшить размер?

0 голосов
/ 15 августа 2013

Я не уверен, извините, если я ошибаюсь, но, возможно, словарь хранится в куче больших объектов, когда его размер превышает 85 КБ (например, байт [90000])

Как Гейб Сказал:

Я вижу, что, возможно, куча больших объектов фрагментируется, и вы не сможете увеличить словарь после точки

Когда LOH фрагментируется, ему иногда не хватает места для хранения объекта с постоянным адресом. Вот что вызывает исключение OutOfMemory. Это больше похоже на пространство Out Of Contigus в исключении LOH.

...