Сборка мусора в .NET (поколения) - PullRequest
21 голосов
/ 11 июня 2009

Я прочитал много статей о производительности .NET, в которых описывается сборка мусора Gen1, Gen2 и объекты, переживающие поколения.

Почему объекты выживают в коллекции?

Что такое пиннинг?

Как мне узнать больше об этом?

Ответы [ 7 ]

30 голосов
/ 11 июня 2009

Одна из причин, по которой у вас несколько поколений в сборщике мусора, - это избегание потери памяти из-за фрагментации.

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

Когда объект переживает коллекцию, он перемещается в более долгоживущее поколение по теории, что если он выжил в одной коллекции, он, вероятно, выживет в других. Таким образом, последующие поколения имеют меньший оборот и не так много фрагментированы. Это означает, что ваша программа тратит меньше времени на жонглирование, чтобы очистить дыры и тратить меньше памяти. Это также улучшение по сравнению с традиционным управлением памятью (malloc / free или new / delete), которое позволяет операционной системе управлять любой фрагментацией памяти.

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

Иногда люди испытывают искушение позвонить GC.Collect(), чтобы заставить сборщика мусора что-нибудь почистить. Возможно, они обнаружили утечку или думают, что память становится слишком фрагментированной. Вы должны сопротивляться этим побуждениям. Хотя сборка мусора в .Net не идеальна, она очень хороша и почти наверняка намного лучше очищает память, чем вы. Скорее всего, если объект можно и нужно собирать, он будет. Помните, что вызов GC.Collect() на самом деле может усугубить ситуацию, помогая сборщику мусора перемещать объекты до более высокого поколения и, таким образом, держать их вокруг дольше, чем они могли бы быть.

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

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

10 голосов
/ 11 июня 2009

http://blogs.msdn.com/maoni/ - хороший ресурс.
Задавать вопросы здесь тоже помогает:)

На ваши вопросы:

Почему объекты выживают в коллекции:
Объекты выживают в коллекции, когда они являются «живыми объектами» или «достижимыми объектами». Доступные объекты - это объекты, на которые есть ссылка на другой объект, который включен:

  1. Стек
  2. Очередь финализации
  3. другой объект более высокого поколения (например, объект Gen2, содержащий ссылку на объект Gen0)
  4. Таблица дескрипторов (структура данных, используемая CLR, для которой требуется отдельный пост :))

Что такое пиннинг:
Закрепление означает, что объект не перемещается в памяти. объекты перемещаются в памяти в результате сжатия GC, вы можете создать GCHandle типизированных закрепленных объектов, если хотите закрепить объект, закрепление также происходит автоматически за областью поиска для объектов, которые передаются в собственный код через PInvoke (например, строки передается в качестве вывода, внутренний буфер закрепляется во время вызова PInvoke).

Проверьте http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.gchandle.aspx для хорошего примера о GCHandle.

3 голосов
/ 23 апреля 2010

Вот короткая, но полная программа , которую я написал для демонстрации сборки мусора 2-го поколения в работающем приложении

http://nomorehacks.wordpress.com/2008/11/27/forcing-the-garbage-collector/

2 голосов
/ 11 июня 2009

http://msdn.microsoft.com/en-us/library/ms973837.aspx

Очень большая тема. Выше хорошее резюме от MS.

2 голосов
/ 11 июня 2009

Я думал эта статья тоже была довольно хороша.

0 голосов
/ 11 июня 2009

Закрепление используется для предотвращения перемещения объектов сборщиком мусора. Это может снизить производительность, ограничивая возможности сборщика мусора. Обычно закрепленные объекты следует закреплять как можно быстрее.

0 голосов
/ 11 июня 2009

Это - интересная статья на эту тему, которая может оказаться информативной.

...