Как сделать сборку мусора в .NET менее частой? - PullRequest
8 голосов
/ 08 февраля 2011

У меня есть приложение, которое обрабатывает большое количество мелких объектов, например, 2000 сообщений в секунду. Одно сообщение составляет примерно 100 байт, может быть, меньше. Приложение работало в течение 6 с половиной часов под нагрузкой, и за это время у него было 264 416 0 th gen коллекций, 166 699 1 st gen и 69 608 2 nd gen. Это 11,6, 7,3 и 3 сбора в секунду соответственно.

Вопрос в том, как сделать сборку мусора менее частой?

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

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

UPD 2 : как предложено в ответ Леппи GC в режиме сервера действительно в 10 раз меньше сборов. Также кажется (как описывает это Рихтер), что частые коллекции - не плохая вещь.

Ответы [ 6 ]

9 голосов
/ 08 февраля 2011

Что заставляет вас думать, что это влияет на вас?В частности, коллекции gen-0 очень, очень дешевы - и их следует поощрять.

Я бы посмотрел больше на "" Что может заставить некоторые из этих запросов перейти из gen-0 в gen-1;я цепляюсь за любой объект без необходимости, например, через событие? ".

Конечно, еще одна вещь, на которую стоит обратить внимание: есть ли места, где вы можете избежать создания ненужных объектов, например:

  • Вы делаете конкатенацию строк в цикле, который может быть StringBuilder вместо?
  • любых коллекций среднего или большого размера, которые можно инициализировать с правильной длиной, чтобы избежать перераспределений?
  • любые буферы очистки, которые могут быть использованы повторно, например, выполняете ли вы большую работу по кодированию, которая кратко использует byte[] в методе, где этот byte[] может быть передан в качестве области очистки или извлечен изпул?
  • любые другие вещи, которые можно кэшировать и использовать повторно - например, new Regex("some literal"), созданный внутри метода, который можно преобразовать в статическое поле, плюс скомпилированный для производительности
  • любой интенсивный разбор строк, который может использовать интернирование? (Хотя не обязательно встроенный интернер)
4 голосов
/ 08 февраля 2011

Вы получите примерно в 10 раз меньше ГХ, если включить gcServer="true" в app.config.Но учтите, что это не повышает производительность, и у вас, скорее всего, будет увеличена задержка в приложении, если оно является настольным приложением.

Вот параметр app.config:

<runtime>
  <gcServer enabled="true"/>
</runtime>
1 голос
/ 29 сентября 2012

Рассматривали ли вы использование типов значений вместо ссылочных типов? Это может быть хорошим вариантом, если «объекты» являются временными и нужны только во время обработки. Типы значений (структуры) размещаются в стеке и, следовательно, не требуют сбора (например, экземпляры классов).

1 голос
/ 08 февраля 2011

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

0 голосов
/ 08 февраля 2011

Может быть, вам стоит подумать об использовании пула объектов или навесов. Более многократно используемые объекты часто приводят к меньшему количеству мусора и делают GC менее частым.

0 голосов
/ 08 февраля 2011

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

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