Ответ 1
Как проверка работоспособности, у меня есть кнопка для принудительного включения GC. Когда я нажимаю это, я быстро возвращаю 6 ГБ. Разве это не доказывает, что мои 6 массивов не были указаны и МОГУТ быть собраны, если бы GC знал/хотел?
Вероятно, вам лучше спросить When does the GC automatically collect "garbage" memory?
. Сверху моей головы:
- Чаще всего, когда генерация 0 заполнена или распределение объектов не помещается в доступное свободное пространство. 1
- Как правило, при распределении блока памяти возникает
OutOfMemoryException
, запускается полный GC, чтобы сначала попробовать и вернуть доступную память. Если после коллекции не будет достаточной непрерывной памяти, тогда будет выбрано исключение OOM.
При запуске сбора мусора GC определяет, какие поколения нужно собирать (0, 0 + 1 или все). Каждое поколение имеет размер, определяемый GC (он может меняться по мере запуска приложения). Если только поколение 0 превысит его бюджет, то это единственное поколение, чей мусор будет собран. Если объекты, оставшиеся в поколении 0, заставят генерацию 1 переходить на ее бюджет, то также будет собрано поколение 1, и его выживающие объекты будут продвинуты до поколения 2 (что является самым высоким поколением в реализации Microsoft). Если также будет превышен бюджет для поколения 2, мусор будет собран, но объекты не могут быть переведены в более высокое поколение, поскольку их не существует.
Итак, вот важная информация, наиболее распространенный способ запуска GC, поколение 2 будет собрано только в том случае, если поколение 0 и поколение 1 заполнены. Кроме того, вам нужно знать, что объекты размером более 85 000 байт не хранятся в обычной куче GC с генерацией 0, 1 и 2. Они фактически хранятся в так называемой большой куче объекта (LOT). Память в LOH освобождается только во время сбора FULL (т.е. При сборке 2); никогда, когда собираются только поколения 0 или 1.
Почему GC не собирался? Если это не время для этого, когда?
Теперь должно быть очевидно, почему GC никогда не происходило автоматически. Вы только создаете объекты в LOH (помните, что типы int
, как вы их использовали, выделяются в стеке и их не нужно собирать). Вы никогда не заполняете поколение 0, поэтому GC никогда не бывает. 1
Вы также запускаете его в 64-битном режиме, а это означает, что вы вряд ли попадете в другой случай, который я перечислял выше, где происходит сбор, когда во всем приложении недостаточно памяти для размещения определенного объекта. Для 64-битных приложений ограничение виртуального адресного пространства составляет 8 ТБ, поэтому через некоторое время вы столкнетесь с этим случаем. Скорее всего, у вас закончится физическая память и файловое пространство страницы, прежде чем это произойдет.
Поскольку GC не произошло, окна начинают выделять память для вашего приложения из доступного пространства в файле страницы.
Я читал много, что говорит, что я не должен называть GC.Collect(), но если GC не собирается в этой ситуации, что еще я могу сделать?
Вызовите GC.Collect()
, если этот тип кода - это то, что вам нужно написать. Еще лучше, не пишите этот код вне тестирования.
В заключение я не сделал справедливости в отношении вопроса об автоматической сборке мусора в CLR. Я рекомендую прочитать об этом (это действительно очень интересно) через сообщения в блоге msdn или, как уже упоминалось, отличную книгу Джеффри Рихтера, CLR Via С#, глава 21.
1 Я исхожу из того, что вы понимаете, что реализация .NET в GC представляет собой сборщик мусора для поколений. В простейших терминах это означает, что вновь созданные объекты находятся в поколении с более низким номером, т.е. Поколении 0. По мере того как сборки мусора запускаются и обнаруживается, что объект, который находится в определенном поколении, имеет корень GC (а не "мусор" ) он будет повышен до следующего поколения. Это улучшение производительности, поскольку GC может занять много времени и повредить производительность. Идея состоит в том, что объекты в более высоких поколениях, как правило, имеют более длительный срок службы и будут использоваться в приложении дольше, поэтому нет необходимости проверять это поколение для мусора так же, как и более низкие поколения. Вы можете прочитать больше в этой статье в википедии. Вы заметите, что это также называется эфемерным GC.
2Если вы не верите мне, после удаления одного из кусков, есть функция, которая создает целую кучу случайных строк или объектов (я бы рекомендовал против массивов примитивов для этого теста), и вы увидите, когда вы достигнете определенное количество пространства, будет иметь место полный GC, освободив память, которую вы выделили в LOH.