Подтвердить что ты не робот

Максимальная память, которую может распределить .NET-процесс

Какова максимальная память, которую сборщик мусора может выделить для процесса .NET? Когда я компилирую в x64, Process.GetCurrentProcess.MaxWorkingSet возвращает около 1,4 ГБ, но когда я компилирую AnyCPU (x64), возвращается такое же число. Для x64 это больше похоже на значение "Limit", которое отображается в диспетчере задач. Как я могу получить правильное число, которое вызовет OutOfMemory-Exceptions при превышении во всех случаях?

Некоторые примеры, на которые должен возвращаться метод:

1) Конфигурация машины: x64-Windows, 4 ГБ физической памяти, 4-страничный файл страницы
-Как 64-битный процесс: 8 ГБ
-Как 32-битный процесс: 1,4 ГБ

2) Конфигурация машины: x64-Windows, физическая память 1 ГБ, файл страницы 2 ГБ

-Как 64-битный процесс: 3 ГБ
-Как 32-битный процесс: 1,4 ГБ

3) Конфигурация машины: x32-Windows, физическая память 4 ГБ, файл страницы 4 ГБ

-Как 64-битный процесс: не произойдет -Как 32-битный процесс: 1,4 ГБ

4) Конфигурация машины: x32-Windows, физическая память 512 МБ, файл страницы 512 МБ
-Как 64-битный процесс: не произойдет -Как 32-разрядный процесс: 1,0 ГБ

4b9b3361

Ответ 1

Windows может быть настроена для размещения большего количества файловых пространств по запросу или по запросу.
Объекты заданий могут помешать потреблению более определенного объема памяти.
Фрагментация кучи и ее генерация (плюс необходимость вкладывать большие вещи в кучу больших объектов)

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

Так как это сложно, любой, кто задает этот вопрос, вероятно, пытается сделать что-то неправильно и должен перенаправить свой вопрос на что-то более полезное.

Что вы пытаетесь сделать, похоже, потребует такого вопроса?

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

Right. это гораздо более сговорчивый вопрос.

Два решения в порядке сложности:

  • Сделайте ваши кеши WeakReferences
    • Это означает, что система будет освобождена системой почти магически для вас, но у вас будет мало контроля над такими вещами, как политика замены.
    • это зависит от того, что кешированные данные намного больше, чем ключ и накладные расходы слабых ссылок
  • Зарегистрируйтесь для извещения о коллекциях мусора
    • Это позволяет вам контролировать освобождение вещей.
    • вы полагаетесь на систему, имеющую соответствующий максимальный размер для генераций GC, которые могут занять некоторое время, чтобы добраться до устойчивого состояния.

Точки для заметок. Неужели так дешево поддерживать этот массивный кеш (переходить на диск по звукам его), чем пересчитывать/повторно запрашивать данные.
Если ваш кеш обнаруживает плохую локальность между обычно/последовательно запрошенными элементами, тогда много усилий будет потрачено на подкачку данных в и из. Меньший кеш с эффективной настраиваемой политикой перераспределения дает хорошие шансы на выполнение значительно лучше (и с гораздо меньшим воздействием на другие запущенные программы).

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

Ответ 2

Разве это не зависит от того, сколько у вас RAM?

В теории, процесс x64 может выделять EB (etabytes?) RAM, я думаю - то есть LOT. Но если вы это сделаете, ваша машина должна начать пейджинг как сумасшедший и вообще умереть.

В 32-битном режиме он был другим, так как вы не могли выделить более 1 ГБ ОЗУ в ЛЮБОЙ процесс в окнах (да, есть способы обойти его, но это не очень). На практике это примерно 7-800 мг на .NET-процесс, так как .NET зарезервировал некоторое пространство.

В любом случае, в 32 бит, вы можете использовать только 3 ГБ - ОС резервирует 1 ГБ виртуального пространства для себя.

В 64 бит это должно быть 2 ^ 64, что является большим числом, но http://en.wikipedia.org/wiki/X86-64 говорит, что это 256 Тбайт виртуального пространства, и 1 ТБ REAL RAM. В любом случае, это намного больше, чем у вас, вероятно, будет на вашей машине, поэтому он попадет в файл с файлами.

С 64-разрядной ОС и 64-разрядной средой выполнения, Приложения на .NET 2.0 теперь могут использовать в 500 раз больше памяти для данных таких как серверные кеши.

У этого есть некоторая хорошая информация, тоже http://www.theserverside.net/tt/articles/showarticle.tss?id=NET2BMNov64Bit

BTW, если вы находитесь на машине x64 (то есть на компьютере x64 или на x64 OS), компиляция для AnyCPU и x64 делает то же самое - она ​​работает в режиме x64. Единственное различие заключается в том, что вы используете AnyCPU vrs x86:

  • x64 OS/.NET, AnyCpu: x64 app
  • x64 OS/.NET, x64: x64 app
  • x64 OS/.NET, x32: x32 app (x64.NET framework как BOTH x32 и x64 версии установленного Fx)

  • x32 OS/NET, AnyCPU: x32 app

  • x32 OS/.NET, x64: CRASH И BURN BABY! (на самом деле, он просто умирает грациозно)
  • x32 OS/.NET, x32: x32.