Hashtable - недостаточно памяти

Я использую Hashtable в своем приложении C #. Я загружаю миллионы ключей, но после того, как приложение превышает 3,7 ГБ ОЗУ, возникает исключение «нехватка памяти».

Я использую операционную систему x64, а на компьютере 16 ГБ оперативной памяти. Я подумал, может быть, это ограничение x86. Я изменил тип сборки на x64, но все равно получаю ошибку.

Есть ли максимальный размер памяти для объекта в .net? Можно как нибудь использовать всю память?

Спасибо, Андрей


person Andrew    schedule 12.01.2010    source источник
comment
Для набора данных такого размера вы можете захотеть использовать дисковое (или частично дисковое) решение. Загружать в память столько данных - нехорошая карма. Взгляните на BerkeleyDB, у него есть привязки .NET, и он бесплатный.   -  person Tamas Czinege    schedule 12.01.2010
comment
RAM не имеет значения; ОЗУ - это просто кеш для ускорения доступа к памяти. Соответствующий дефицитный ресурс - это доступное адресное пространство.   -  person Eric Lippert    schedule 12.01.2010
comment
Эрик Липперт: Я не знаю, прокомментировали ли вы вопрос или мой комментарий, но я имел в виду то, что (помимо ограниченного адресного пространства) загрузка такого количества данных с диска занимает очень много времени (тем более, что / если это выгружаются).   -  person Tamas Czinege    schedule 13.01.2010
comment
Правильно; Я понимаю, что вопрос, который начинается, «У меня заканчивается память, но у меня много оперативной памяти», демонстрирует непонимание того, что на самом деле исчерпывается. У вас может быть 256 мегабайт ОЗУ, но при этом у вас останется двадцать программ, каждая из которых использует 500 мегабайт адресного пространства; машина будет медленной, но у вас не закончится адресное пространство. И у вас может быть 14 ГБ пустой оперативной памяти, а адресное пространство по-прежнему исчерпывается. Объем ОЗУ совершенно не имеет отношения к вопросу об исчерпании адресного пространства; это касается только производительности.   -  person Eric Lippert    schedule 13.01.2010


Ответы (5)


Взгляните на этот предыдущий ответ: Максимальное использование памяти .NET 2 ГБ даже для x64 сборок

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

person Rubens Farias    schedule 12.01.2010
comment
+1, избили меня, пока я печатал. См. Также: blogs.msdn.com/ericlippert/archive/2009/06/08/ - person Sapph; 12.01.2010
comment
@Sapph, ты за эту ссылку, я искал ее, чтобы дополнить этот ответ =) - person Rubens Farias; 12.01.2010

Используйте Dictionary<,> вместо HashTable. В HashTable и ключ, и значение являются объектами, поэтому, если они являются типами значений, они будут упакованы. Dictionary может иметь типы значений как ключ и / или значение, что требует меньше памяти. Если вы, например, используете в качестве ключа int, каждый будет использовать 28 байтов в HashTable, тогда как они используют только 4 байта в Dictionary.

Если и ключ, и значение являются типами значений и используют менее 8 байтов, Dictionary сможет содержать больше элементов, чем HashTable.

person Guffa    schedule 12.01.2010

В этой статье говорится, что .NET ограничивает размер одного возражать на два гигабайта.

person Daniel Brückner    schedule 12.01.2010

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

Я попробовал идею "Guffa" использовать словарь на небольшой пример хеш-таблицы, и получившийся словарь фактически увеличился в размере!

Его предложение заставило меня задуматься о том, что я на самом деле писал в Hashtable. Итак, я просмотрел эту страницу и решил, что на самом деле не нужно было хранить данные типа Long, Integer было более чем достаточно. Я знаю, что, вероятно, рассказываю всем вам, гуру, то, что ослепительно очевидно, но я смог уменьшить результирующие сериализованные hastables (всего их 12) с 81,9 МБ до 69,4 МБ, просто объявив переменные как целые числа вместо Long.

На самом деле это не решило мою проблему, но, безусловно, уменьшит время, необходимое для их загрузки обратно в память.

person Hornbydd    schedule 08.05.2012

Проблема не имеет ничего общего с объемом физической ОЗУ в вашей системе или от того, скомпилирован ли x64 или нет. Также неверно, что .NET должен ограничивать объекты до 2 ГБ. (Вы можете исследовать кучу больших объектов .NET 4.5 для получения дополнительной информации.) Причина, по которой вы получаете сообщение «Недостаточно памяти», заключается в том, что процесс не может отобразить непрерывный раздел памяти запрошенного вами размера.

У Эрика Липперта отличный статья в блоге по этой теме, и я заметил, что он прокомментировал этот вопрос, но, к сожалению, не ответил на него.

Итак, вот ответ: примите тот факт, что объем памяти, который вы ищете с помощью этой реализации, недоступен, и решите вашу проблему, разбив его на более мелкие фрагменты.

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

person Thane Plummer    schedule 22.11.2017