Проблема управления памятью .Net: объекты, застрявшие в поколении 2 - PullRequest
1 голос
/ 19 февраля 2011

Я профилировал свой профилировщик App w / VS2010 с включенным сбором времени жизни объекта.
Я был сильно удивлен, увидев, что большинство экземпляров определенной структуры с именем «Запись» собираются GC как экземпляры Gen 2.Я очень расстроен, так как экземпляры структуры «Запись» должны жить менее 500 мс каждый (теоретически).

Эти структуры представляют собой простые данные временного ряда 6xInt32 или около того, которые считываются в потоке, помещаются в очередь / помещаются в очередь размером 1000, передаются в процессор, который запускает некоторую логику в зависимости от этих нескольких миллионов«Записи» последовательно.Мне не нужно хранить более 50 записей одновременно.

Итак, мой вопрос: почему эти объекты могут жить достаточно долго, чтобы в основном оказаться ссылками второго поколения, и что я могу сделать, чтобы они действительно ДЕЙСТВИТЕЛЬНОполучить сброс после каждого вычисления.

РЕДАКТИРОВАТЬ: Я спрашиваю об этом, потому что я заметил резкое падение производительности для больших размеров выборки (например, номера записей): еслиN занимает T минут, 2N занимает 2,5T минут или около того и т. Д.
Так что, очевидно, где-то есть утечка.

РЕДАКТИРОВАТЬ 2: Мое плохое: создание экземпляра структуры не может привести к сбору мусора. Я изменил его на классы и пока не заметил значительного улучшения.Я снова запускаю профилировщик с классами, на этот раз не структурированными) и посмотрю, что он дает

РЕДАКТИРОВАТЬ 3: Многие ответы подозревают, что где-то произойдет бокс / распаковка,Я действительно использую типизированные общие коллекции и типизированные очереди.И «Записи» никогда не прикрепляются ни к какому классу в качестве участников.Они индивидуально обрабатываются событиями.Бывший Struct (теперь Class) реализовал интерфейс и был вызван им при вызове (это довольно распространенное использование), и я отключил этот интерфейс.Без улучшений.

РЕДАКТИРОВАТЬ 4: Я снова запустил профилировщик, заменив struct на class.У меня те же результаты:
большинство экземпляров CLASS"Запись" все еще в конечном итоге собираются как экземпляры Gen2

РЕДАКТИРОВАТЬ 5: Производители классов Record много параллельных BackGroundWorkers (Byte Readers), и есть один Поток Потребителя, который отправляет Записи другим методам после выполнения нескольких проверок.Кроме того, я использую События и Делегаты для связи между различными частями.Я не отменяю регистрацию этих событий, потому что они полезны на протяжении всего процесса (я могу ошибаться в этом вопросе)

Ответы [ 3 ]

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

Если вы «сильно загружены» памятью и используете C # 4.0, вы можете попробовать «серверный» GC. Объедините ваш app.config (или web.config) с:

<configuration>
  <runtime>
    <gcServer enabled="true"/>
  </runtime>
</configuration>

(со слиянием я имею в виду, что если у вас уже есть некоторые из этих разделов, используйте их, в противном случае создайте их. "Конфигурация" - это элемент первого уровня app.config). Это лучше для некоторых приложений (приложений, которым не нужно интенсивное взаимодействие с пользователем)

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

Если вы сохранили их как локальные переменные (что может или не может быть возможным в зависимости от вашего сценария), они никогда не окажутся в куче вообще.

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

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

Также вы рассматривали возможность использования шаблона Flyweight ?

Edit- Поскольку теперь вы говорите, что делаетечто-то с событиями, это, скорее всего, будет причиной ваших проблем.Вы забыли отменить регистрацию событий?

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

Они заканчивают как Второе Поколение, потому что GC просто решил не собирать их мусор. Я не думаю, что это действительно проблема для беспокойства. Если вы действительно хотите, вы можете просто повторно использовать 1000 объектов вместо того, чтобы постоянно создавать новые. Это сделало бы так, чтобы этим объектам не нужно было собирать мусор. Вы можете заставить сборщик мусора гарантировать, что объекты «ДЕЙСТВИТЕЛЬНО» будут выгружены, но это снизит производительность, так как GC - дорогая операция, или мне так сказали.

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