Почему возникает исключение нехватки памяти, если память доступна? - PullRequest
9 голосов
/ 27 июня 2010

У меня довольно простое приложение на C #, которое создает большую хеш-таблицу.Ключами этой хеш-таблицы являются строки, а значения - целые.

Программа работает нормально, пока в хеш-таблицу не добавлено около 10,3 миллиона элементов, когда в строке, добавляющей элемент, возникает ошибка нехватки памятив hasbtable.

Согласно диспетчеру задач, моя программа использует только 797 МБ памяти, и все еще доступно более 2 ГБ.Это 32-разрядная машина, поэтому я знаю, что только один процесс может использовать только 2 ГБ, но все равно остается около 1,2 ГБ, в которую должна расширяться хеш-таблица.

Почему бы изОшибка памяти будет выброшена?

Ответы [ 7 ]

11 голосов
/ 27 июня 2010

Теоретически вы получаете 2 ГБ для процесса, но реальность такова, что это 2 ГБ непрерывной памяти, поэтому, если память вашего процесса фрагментирована, вы получите меньше, чем это.

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

Если вы знаете размер, который необходимо опередить (или имеете разумную завышенную оценку), это может помочь указать емкость в конструкторе.

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

4 голосов
/ 27 июня 2010

Возможно, это связано с фрагментацией памяти: у вас все еще есть свободная память, но она не смежна.Память разделена на страниц , обычно размером 4 КБ, поэтому, если вы выделите 4 МБ, вам потребуется 1024 смежных страницы памяти в адресном пространстве вашего процесса (они не должны быть физически непрерывно, так как память виртуализирована для каждого процесса).

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

3 голосов
/ 27 июня 2010

Используйте Process Explorer (www.sysinternals.com) и посмотрите на виртуальное адресное пространство вашего процесса.В отличие от «Частных байтов» (то есть объема памяти, занятого процессом), виртуальное адресное пространство показывает самый высокий используемый адрес памяти.Если фрагментация высока, она будет намного выше, чем «Частные байты».

Если вашему приложению действительно требуется такой объем памяти:

  • Рассмотрите возможность перехода на 64-битную
  • Включите флаг / LARGEADDRESSAWARE, который предоставит вашему 32-разрядному процессу 4 ГБ ОЗУ под 64-разрядной операционной системой и 3 ГБ, если 32-разрядная Windows загружена с флагом / 3 ГБ.
1 голос
/ 27 июня 2010

Программа, которую вы запускаете, имеет ограниченные ресурсы благодаря отладчику Visual Studio, пытающемуся отслеживать все, что вы делаете в своем приложении (точки останова, ссылки, стек и т. Д.).

ВКроме того, у вас может быть больше вещей, которые все еще нездоровы, чем вы думаете - сборщик мусора многоуровневый и медленно собирает крупные объекты очень .

    +-------+
    | large |       collected less often (~1/10+ cycles)
  +-+-------+-+              |
  |   medium  |              |
+-+-----------+-+            V
|     small     |   collected more often (~1/3 cycles)
+---------------+

ПРИМЕЧАНИЕ.из памяти, так что возьмите его с крошкой соли.

1 голос
/ 27 июня 2010

Вы просто смотрите не на тот столбец.Взгляните на столбец «Размер коммита», этот размер должен быть около 2 ГБ.

http://windows.microsoft.com/en-us/windows-vista/What-do-the-Task-Manager-memory-columns-mean

0 голосов
/ 28 марта 2013

Я решил свою версию этой проблемы, сняв флажок «Предпочитать 32-разрядный» на странице свойств проекта exe на вкладке «Сборка»

0 голосов
/ 27 июня 2010

Вы должны использовать что-то вроде гибрида между массивом и связанным списком.Поскольку связанный список занимает больше памяти на элемент, чем массив, но массиву требуется непрерывное пространство памяти.

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