Что запускает сборку мусора gen2? - PullRequest
21 голосов
/ 27 мая 2011

У меня странная ситуация, которую я пытаюсь выяснить.

Genesis:

Я запускаю свою программу на физической машине с 16 ядер и 128ГБ ОЗУ.Я пытаюсь определить, почему он не использует все доступные ядра, обычно он использует процессор в среднем на 20-25% (то есть 4-5 ядер из 16).Когда я смотрю на счетчики производительности, они показывают порядка 60-70% времени в сборке мусора.

Для справки, я использую .NET Framework 4 и TPL (Parallel.ForEach) для потоковой передачи производительности.интенсивная часть моей программы.Я ограничиваю количество потоков количеством ядер.

Проблема:

Я создавал большое количество объектов, слишком много для сборщика мусораобрабатывать эффективно и, таким образом, он провел большое количество времени в сборщике мусора.

Простое решение на данный момент:

Я ввел пул объектов, чтобы уменьшить нагрузку на сборщик мусора.Я продолжу объединять объекты в пул для повышения производительности, уже объединяя некоторые объекты, уменьшив сборку мусора с 60–70% времени до 45% времени, и моя программа работала на 40% быстрее.

* 1027один, я надеюсь, вы ответите за меня):

Моя программа при запуске использует не более 14 ГБ доступной оперативной памяти, по сравнению со 128 ГБ ОЗУ, это довольно мало.На этой машине больше ничего не работает (для меня это просто тестовый стенд), и там достаточно оперативной памяти.

  • Если имеется достаточно ОЗУ, почему вообще возникают какие-либо коллекции gen2 (или полные)?Встречается довольно большое количество этих коллекций gen2 (в тысячах).то есть как это определяет порог, чтобы начать коллекцию gen2?
  • Почему сборщик мусора просто не задерживает полные сборы до тех пор, пока нагрузка на физическую память не достигнет более высокого порога?
  • Есть ли способ настроить сборщик мусора так, чтобы он ожидал более высокого порога?(т.е. вообще не надо собирать, если в этом нет необходимости)

РЕДАКТИРОВАТЬ:

Я уже использую возможность использовать серверный сборщик мусора ... чтоМне нужно знать, что вызывает сборку gen2, а не то, что сборщик мусора на сервере лучше (я это уже знаю).

Ответы [ 2 ]

19 голосов
/ 27 мая 2011

Насколько я помню, Client GC используется по умолчанию. Мой опыт показывает, что куча не становится слишком большой перед сбором. Для обработки тяжелых приложений я использую «сервер» GC.

Вы включаете GC сервера в файле конфигурации приложения:

<?xml version ="1.0"?>
<configuration>
  <runtime>
    <gcServer enabled="true"/>
  </runtime>
</configuration>

Для меня это огромная разница в производительности. Например, одна из моих программ тратила более 80% своего времени на сборку мусора. Включение сервера GC снизило это значение до чуть более 10%. Использование памяти возросло, потому что GC позволил ей уйти, но для большинства моих приложений это нормально.

Еще одна вещь, которая вызовет коллекцию Gen 2, - это куча больших объектов. См. CLR Наизнанку: обнаружена куча больших объектов . Короче говоря, если вы превысите порог LOH, он вызовет сбор Gen 2. Если вы выделяете много короткоживущих крупных объектов (около 85 килобайт), это будет проблемой.

5 голосов
/ 27 мая 2011

Из расплывчатой ​​памяти и прочтения: http://msdn.microsoft.com/en-us/library/ee787088.aspx, Я думаю, что одним триггером GC 2-го поколения может быть заполнение сегмента 2-го поколения. В статье говорится, что Server GC использует большие сегменты, поэтому, как уже отмечалось, это, вероятно, важно для вашей производительности.

Если машина подождет, пока у нее практически не будет свободной памяти, это означает, что на каком-то этапе вы получите один адски ГХ. Это, вероятно, не идеально. Если ваше время в GC настолько велико, это признак того, что вы выделяете слишком много объектов, которые выживают достаточно долго, чтобы пройти поколения 0 и 1, и делаете это повторяющимся образом. Если использование памяти вашим приложением со временем не увеличивается, это указывает на то, что эти объекты фактически недолговечны, но живут достаточно долго, чтобы выдержать коллекцию 0 и 1. Это плохая ситуация - вы выделяете недолговечный объект, но платите полную стоимость сбора Gen 2 для его очистки.

Если это так, у вас есть несколько разных направлений:

  1. Постарайтесь сделать коллекцию недолговечных объектов быстрее (чтобы они не добрались до 2-го поколения и, следовательно, стоимость GC ниже)
  2. Старайтесь выделять меньше недолговечных объектов (поэтому GC происходят реже, и у вас есть больше времени, чтобы закончить использование ваших недолговечных объектов, прежде чем выделения заставят GC и объекты будут перемещены в старшие поколения)
  3. Использование типов значений, выделенных в стеке, вместо ссылочных типов для недолговечных объектов (если это соответствует вашим целям)
  4. Если вы знаете, что вам нужен большой кусок этих объектов, объедините их заранее. Похоже, вы делаете это, но должно быть еще много распределения, чтобы удерживать GC на уровне 45%. Если ваш пул недостаточно велик, выделите больше заранее - как вы говорите, у вас достаточно свободной памяти.

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

ГХ доволен временными объектами с коротким сроком службы (например, быстро собираемыми ГК) или долгосрочными / постоянными объектами с длительным сроком службы. Распределение множества объектов в середине этих двух категорий - вот где вы чувствуете боль. Поэтому распределите их меньше или измените время их жизни в соответствии со сценарием их использования.

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