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

Когда память, выделенная .NET-процессом, выпущена обратно в Windows

Настройка

.NET выделяет память для каждой кучи поколений (0, 1, 2, LOH) в сегментах, чтобы получить непрерывный блок памяти при запуске и когда он пытается удовлетворить запрос на распределение после коллекции.

Эта память, выделенная для каждой кучи, скорее всего, выровняется по мере того, как приложение "разогревается", за исключением потенциально для поколения 2 и большой кучи объектов. Во время сбора мусора каждая куча (0, 1, 2) прокачивается и уплотняется, за исключением крупной кучи объекта (LOH), которая просто подметается.

Я понимаю, что "часть развертки коллекции" означает, что GC идентифицирует, какие объекты больше не укоренены и доступны для сбора (или финализации), и что "compact" означает, что адреса, которые все еще живы в куче, реорганизованы так что доступная оставшаяся куча имеет больше непрерывной памяти.

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

Вопрос

Мой вопрос сводится к тому, что происходит с этой памятью в каждой куче, то есть не используется приложением (совершено) больше, но по-прежнему сохраняется .NET? Когда он будет выпущен обратно в ОС?.

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

Нет заблокированного финализатора, и все выглядит здоровым для процесса - возможно, он работал несколько недель, прежде чем он вызвал предупреждение монитора (например,).

Попытка уточнить вопрос, если вы читаете Tess Управление памятью в формате .NET - аналог ресторана, если таблицы являются сегментами кучи, ли ресторан когда-либо теряет таблицы (например, свободные сегменты кучи)?

Edit

  • Устранена путаная ссылка на рабочий набор и цыплят
  • Добавлена ​​ссылка на аналог ресторана Tess.
4b9b3361

Ответ 1

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

ОС управляет виртуальной памятью всех процессов в системе и гарантирует, что одна программа не запустит всю ОЗУ в системе в ущерб другим программам. Когда среда выполнения .NET запрашивает память из системы для использования в кучах, но затем не использует ее, эта память будет (если система будет низкой на свободной ОЗУ) будет перемещена на диск, поскольку к ней не обращаются.

Уточнение по электронной почте из Tess: (выделено мной)

Размеры сегмента остаются неизменными на протяжении всего приложения, но здесь есть две вещи.

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

  • Если сегмент больше не используется, т.е. если вы выполняете GC в сегменте, чтобы он больше не содержал никаких .net-объектов, виртуальный адрес возвращается обратно в ОС.

Принимая это на веру, затем сегменты кучи (таблицы ресторанов) будут возвращены обратно в ОС.

Ответ 2

Я не знаю ответа на этот вопрос, но я подозреваю, что .NET не выпускает свои кучи до тех пор, пока процесс не завершится (и, возможно, при разгрузке AppDomain, по предположению). Это основано только на том, что я наблюдаю за счетчиками памяти .NET. Общие счетчики байтов GC показывают, по крайней мере, в моем приложении, что зарезервированные байты идут вверх и вниз немного по сравнению с жизнью моего приложения, например около 30 МБ.

И если GC работает в режиме сервера, возможно,.NET выпускает память чаще.