Нежелательная сборка мусора - PullRequest
7 голосов
/ 05 января 2012

В заголовке "Принудительная сборка мусора" из книги "C # 2010 и платформа .NET 4" Эндрю Троелсена написано:

"Опять же, вся цель сборщика мусора .NET - это управление памятью от нашего имени. Однако в некоторых очень редких случаях может быть полезно программно форсировать сборку мусора с помощью GC.Collect (). В частности:

• Ваше приложение собирается ввести блок кода, который вы не хотите прерывать возможной сборкой мусора. ... «

Но остановись! Есть ли такой случай, когда сборка мусора нежелательна? Я никогда не видел / читал что-то подобное (из-за моего небольшого опыта разработки, конечно). Если во время вашей практики вы сделали что-то подобное, пожалуйста, поделитесь. Для меня это очень интересный момент.

Спасибо!

Ответы [ 6 ]

7 голосов
/ 05 января 2012

Да, абсолютно возможен случай, когда сборка мусора нежелательна: когда пользователь ожидает, что что-то произойдет, и ему приходится ждать дольше, потому что код не может продолжить работу, пока сборка мусора не будет завершена.

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

5 голосов
/ 05 января 2012

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

Все это делается при загрузке веб-приложения и, вероятно, занимает 4-5 секунд.После этого я вызываю GC.Collect();, потому что я бы предпочел повторно запросить всю эту память сейчас, а не блокировать все потоки во время входящего HTTP-запроса, пока сборщик мусора теряет чистку всех этих недолговечных объектов.Я также считаю, что лучше очистить сейчас, поскольку куча, вероятно, менее фрагментирована в это время, так как мое приложение на самом деле больше ничего не делало до сих пор.Задержка этого может привести к тому, что будет создано гораздо больше объектов, и куча должна быть сжата больше, когда GC запускается автоматически.

Кроме этого, за мои 12 лет программирования на .NET я никогда не сталкивался сситуация, когда я хотел заставить сборщик мусора работать.

3 голосов
/ 05 января 2012

Рекомендация заключается в том, что вам не следует явно вызывать Collect в своем коде. Можете ли вы найти обстоятельства, где это полезно?

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

Вызов Collect не в ту точку ухудшит вашу производительность. Что еще хуже, полагаться на это делает ваш код очень хрупким. Редкие условия, необходимые для того, чтобы сделать вызов Collect полезным или, наконец, не вредным, могут быть полностью отменены простым изменением кода, которое приведет к неожиданным OOM, вялой производительности и тому подобному.

2 голосов
/ 05 января 2012

Я называю это перед измерением производительности, чтобы ГХ не искажал результаты.

Другая ситуация - это тестирование модульных тестов на утечки памяти:

object doesItLeak = /*...*/; //The object you want to have tested
WeakReference reference = new WeakRefrence(doesItLeak); 
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();

Assert.That(!reference.IsAlive);

Кроме того, яне сталкивался с ситуацией, в которой это действительно было бы полезно.
Особенно в производственном коде, GC.Collect никогда не должно быть найдено ИМХО.

1 голос
/ 06 января 2012

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

Очень подозрительный аргумент (который, тем не менее, часто используется).

Windows не является ОС реального времени. Ваш код (Thread / Process) всегда может быть прерван планировщиком ОС. У вас нет гарантированного доступа к процессору.

Итак, все сводится к следующему: как время запуска ГХ сравнивается с временным интервалом (~ 20 мс)?

Существует очень мало достоверных данных об этом, я искал несколько раз.

По моим собственным наблюдениям (очень неформально), коллекция gen-0 составляет <40 мс, обычно намного меньше. Полный Gen-2 может работать в ~ 100 мс, возможно, больше. </p>

Таким образом, «риск» прерывания GC имеет тот же порядок величины, что и обмен на другой процесс. И вы не можете контролировать последнее.

1 голос
/ 05 января 2012

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

...