Когда и как происходит подкачка управляемой кучи .NET?

Мой небольшой стресс-тест, который выделяет массивы произвольной длины (каждый по 100..200 МБ) в цикле, показывает различное поведение на 64-битной машине с Win7 и на 32-битной XP (в виртуальной машине). Обе системы сначала обычно выделяют столько массивов, сколько поместится в LOH. Затем LOH становится все больше и больше, пока доступное виртуальное адресное пространство не будет заполнено. Пока ожидаемое поведение. Но затем — при дальнейших запросах — оба ведут себя по-разному:

В то время как в Win7 выбрасывается OutOfMemoryException (OOM), в XP кажется, что куча увеличивается и даже перемещается на диск - по крайней мере, OOM не выбрасывается. (Не знаю, может ли это быть связано с тем, что XP работает в виртуальной машине.)

Вопрос: Как среда выполнения (или ОС?) принимает решение, будь то для управляемых запросов на выделение памяти, если она слишком велика для выделения, генерируется OOM или куча больших объектов увеличивается - в конечном итоге даже перемещается на диск? Если он поменялся местами, когда происходит OOM?

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

@Edit: приложение является 32-битным приложением, поэтому работает в 32-битном режиме на Win 7.


person user492238    schedule 16.01.2011    source источник
comment
до физического адресного пространства вы не имеете в виду виртуальное адресное пространство этого процесса?   -  person CodesInChaos    schedule 16.01.2011
comment
И ваша программа настроена на AnyCPU или на 32BitOnly? Нехватка памяти в 64-битной программе не должна происходить легко. Я ожидаю, что компьютер остановится из-за чрезмерной подкачки задолго до этого.   -  person CodesInChaos    schedule 16.01.2011
comment
вы правы: имелось в виду виртуальное адресное пространство. И да, прога компилируется в 32 битное приложение, работает WOW на Win7.   -  person user492238    schedule 16.01.2011


Ответы (1)


Применяются обычные правила, управляемый процесс не обрабатывается диспетчером памяти Windows иначе. Конечным источником блоков памяти является диспетчер памяти Windows. Если он не может найти дыру в адресном пространстве виртуальной памяти, соответствующую запрошенному выделению памяти, вызов VirtualAlloc() завершается ошибкой, и среда CLR генерирует OOM.

То же самое для поведения подкачки: если страницы в ОЗУ необходимы для сопоставления страниц других процессов или даже страниц того же процесса, они будут заменены. Это никак иначе не связано с OOM.

Вы не можете предположить, что он будет работать на XP точно так же, как и на Win7 x64. Получение OOM на x64 при создании программы, ориентированной на AnyCPU, довольно необычно, 64-разрядная операционная система имеет очень большое адресное пространство виртуальной памяти. Верхний предел задается максимальным размером файла подкачки. 32-разрядная программа будет работать на уровне эмуляции WOW, она может иметь адресное пространство 4 ГБ, если вы установите бит опции LARGEADDRESSAWARE в Editbin.exe.

Вы можете использовать утилиту SysInteral VMMap, чтобы увидеть, как распределено адресное пространство вашего процесса.

person Hans Passant    schedule 16.01.2011
comment
Если он не может найти дыру в адресном пространстве виртуальной памяти, соответствующую запрошенному выделению памяти, вызов HeapAlloc() завершается ошибкой, и CLR генерирует OOM. - а почему халтура не пейджинговая чем? По крайней мере, должен, если виртуальное пространство еще не полностью израсходовано, а другой оперативной памяти найти не удалось? - person user492238; 16.01.2011
comment
Две очень разные вещи. Пейджинг происходит, когда необходимо найти физический объем памяти. ОЗУ. Выделение памяти происходит в виртуальной памяти. 32-битный процесс занимает 2 гигабайта, независимо от того, сколько оперативной памяти установлено. Сумма всей виртуальной памяти, выделяемой всеми процессами, ограничивается только файлом подкачки, а не оперативной памятью. - person Hans Passant; 16.01.2011
comment
Итак, 2 ГБ (некоторые ТБ на 64-битной версии) — это только теоретические ограничения? Диспетчер памяти переключается до тех пор, пока размер part файла подкачки, зарезервированного для процесса, не будет заполнен? И если эта часть даже помещается в ОЗУ, она вообще не меняется местами? Это ответит на вопрос - person user492238; 16.01.2011
comment
Верен только последний комментарий. Я бы порекомендовал Windows Internals для большего понимания. - person Hans Passant; 16.01.2011
comment
последнее предложение должно звучать так: А если виртуальная память для процесса полностью помещается в ОЗУ, она даже не подкачивается вообще? - person user492238; 16.01.2011
comment
@Hans - Означает ли это, что если у машины 32 ГБ физической оперативной памяти, файл подкачки необходимо настроить так, чтобы он мог увеличиваться как минимум до 32 ГБ, чтобы использовать полные 32 ГБ физической памяти? - person Aaron Carlson; 16.01.2011
comment
Что ж, значительная его часть будет использоваться кешем файловой системы. Но да, если вы хотите иметь возможность запускать процесс, которому требуется 32 ГБ или более, вам понадобится такой же большой файл подкачки. Настройка по умолчанию в 1,5 раза больше размера ОЗУ, что позволяет увеличить его. Для настройки размера файла подкачки задавайте вопросы на superuser.com - person Hans Passant; 16.01.2011
comment
@Ханс Пассант; Что касается части о LARGEADDRESSAWARE, 32-разрядный процесс имеет виртуальную память 4 ГБ, 2 ГБ для пользовательского пространства и 2 ГБ, сопоставленных с ядром. Если вы установите LAA, это означает, что 32-битный процесс будет иметь 3 ГБ для пользовательского пространства и 1 ГБ для ядра. Для оригинального автора; погуглите термины PAE, Large address extensions, AWE - очень интересно ;) - person Erti-Chris Eelmaa; 05.10.2014
comment
Нет, эти предположения действительны только для 32-разрядной операционной системы. Параметр загрузки /3GB сам по себе уже давно не актуален, даже в 32-битной ОС. - person Hans Passant; 05.10.2014