Как заставить .NET раскрыть неиспользуемую ОЗУ?

Вот статистика для моей программы после того, как она использовала память чрезвычайно интенсивно, потребляя 6 ГБ на своем пике, но затем сохраняя все на диск и оставляя очень мало по объему:

Screenshot

Соблюдайте, что почти все вышло за рамки и было собрано мусор - размеры кучи крошечные. И все же .NET сохраняет 181 МБ.

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

Ответ 1

В соответствии с CLR Inside Out - куча больших объектов не открыта, CLR отменяет неиспользуемую память во время сборки мусора Gen 2.

Это означает, что вы можете либо ждать, когда коллекция мусора Gen 2 произойдет сама по себе, либо вы можете заставить ее использовать GC.Collect() - вам действительно нужно знать, что вы делаете, если вы выберете этот маршрут, однако, поскольку он смешивает с сборщиками мусора стандартные циклы сбора мусора, которые могут действительно испортиться с производительностью:

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

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

Вы также должны подумать, действительно ли это проблема:

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

Обновление: Расширенная отладка .NET: управляемая куча и сборка мусора, похоже, подтверждает гипотезу о том, что память только uncommitted во время генерации 2/полной коллекции:

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