Сомнения в .NET Сборщик мусора - PullRequest
9 голосов
/ 08 апреля 2010

Я прочитал несколько документов о сборщике мусора .NET, но у меня все еще есть некоторые сомнения (примеры в C #):

1) GC.Collect () вызывает частичную или полную коллекцию?2) Блокирует ли частичный сбор выполнение приложения-жертвы?Если да ... то я полагаю, что это очень "легкие" вещи, так как я использую игровой сервер, который использует 2-3 ГБ памяти, и у меня "никогда" нет остановок выполнения (или я их не вижу ..)).3) Я читал о корнях GC, но до сих пор не могу понять, как именно они работают.Предположим, что это код (C #):

MyClass1:

[...] 
public List<MyClass2> classList = new List<MyClass2>(); 
[...]

Main:

main()
    {
     MyClass1 a = new MyClass1();
     MyClass2 b = new MyClass2();
     a.classList.Add(b);

     b = null;

     DoSomeLongWork();
    }

Будет ли b когда-либо иметь право на сборку мусора (доDoSomeLongWork заканчивается)?Ссылка на b, которая содержится в classList, может ли она считаться корнем?Или рут это только первая ссылка на экземпляр?(я имею в виду, b является корневой ссылкой, потому что там происходит создание экземпляра).

Ответы [ 5 ]

5 голосов
/ 08 апреля 2010
  1. Существует несколько перегрузок для GC.Collect. Тот без параметров делает полный сбор. Но имейте в виду, что редко стоит вызывать GC явно.

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

  3. Думайте о корне как о допустимой ссылке. В вашем примере экземпляр MyClass2 не будет собран, если на него еще есть ссылки. То есть если экземпляр, на который указывает a, все еще имеет root-права, ваш экземпляр MyClass2 будет таким же. Также имейте в виду, что GC гораздо более агрессивен в сборках в режиме выпуска, чем в отладочных сборках.

3 голосов
/ 08 апреля 2010
  1. GC.Collect () делает полную коллекцию. Вот почему не стоит называть это самим, поскольку это может преждевременно продвигать объекты до поколения

  2. AFAIK, не совсем. GC блокирует так мало времени, чтобы быть несущественным.

  3. Корень GC стека - это объект, на который в данный момент ссылается метод в стеке. Обратите внимание, что поведение между сборками отладки и выпуска отличается; при сборках отладки все переменные в методе остаются живыми до тех пор, пока метод не вернется (поэтому вы можете увидеть их значение в окне отладки). В выпусках сборки CLR отслеживает, где используются переменные метода, и GC может удалять объекты, на которые ссылается текущий выполняемый метод, но которые не используются в разделе метода, который еще должен выполняться.

Итак, в вашем примере на a и b больше не ссылаются после вызова DoSomeLongWork(), поэтому в выпусках сборки во время выполнения этого метода они оба будут иметь право на сбор. В отладочных сборках они будут зависать, пока не вернется метод main().

2 голосов
/ 08 апреля 2010

Сборка мусора автоматическая . Вам не нужно вмешиваться, если вы не имеете дело с неуправляемыми ресурсами. Мусор собирается каждый раз, когда объект выходит из области видимости; и через определенные промежутки времени, когда сборщик мусора считает это необходимым - например, ОС требует памяти. Это означает, что нет никаких гарантий относительно того, как скоро это произойдет, но ваше приложение не исчерпает память, пока память из этих объектов не будет извлечена.

Будет ли b когда-либо иметь право на сборку мусора (до завершения DoSomeLongWork)?

Да, когда сборщик мусора сочтет это необходимым.

Оформление заказа Основные сведения о сборщике мусора и советы по производительности

1 голос
/ 16 августа 2010

Будет ли b когда-либо иметь право на сборку мусора (до завершения DoSomeLongWork)?

Потенциально да, при условии, что a и b исключены компилятором из набора глобальных корней (то есть не хранятся в стеке), после чего они могут быть восстановлены коллекцией в течение DoSomeLongWork.

Я обнаружил случаи, когда .NET восстанавливает, но моно пропускает память .

Ссылка на b, содержащаяся в classList, может ли она считаться корнем?

Будет ли b превращен в глобальный корень, полностью зависит от компилятора.

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

  • Компиляторы качества производства выполняют сложное распределение регистров и поддерживают только действующие ссылки в стеке, перезаписывая или обнуляя ссылки в стеке по мере их смерти. В этом случае b не работает во время вызова DoSomeLongWork, поэтому его запись в стеке будет обнуляться или перезаписываться.

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

Или корень - это только первая ссылка на экземпляр?

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

1 голос
/ 08 апреля 2010
  1. Да, GC.Collect () выполняет полный сбор, но вы можете выполнить ручной сбор GC.Collect (0), чтобы сделать только ген 0.1006 * Все коллекции блокируют потоки, но частичная сборка делает это очень кратко.

  2. Нет, экземпляр MyClass2 все еще доступен в другом списке.И a, и b являются корневыми ссылками (во время DoSomeLongWork), но, поскольку b является нулем, это не имеет значения.Обратите внимание, что GC тесно связан с концепцией ссылочных типов.b является только локальной переменной, ссылающейся на анонимный объект.«Корнями» для GC являются статические поля, все в стеке и даже регистры процессора.Проще говоря: все, к чему у вашего кода есть доступ.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...