Объект не мусор, но не содержит gcroots - PullRequest
13 голосов
/ 02 марта 2009

Здесь мы сталкиваемся с проблемой с нашим веб-приложением. (Asp.net 2.0 Win server 2008)

Наше использование памяти для веб-сайта растет и растет, хотя я ожидаю, что оно останется на довольно статическом уровне. (У нас есть небольшое количество данных, которые хранятся в состоянии).

Желая выяснить, в чем проблема, я запустил System.GC.Collect (); несколько раз брал дамп памяти и затем загружал этот дамп памяти в WinDbg.

Когда я делаю DumpHeap -Stat, я получаю неоправданно большое число для определенного типа, зависшего в памяти.

0000064280580b40 713471 79908752 Оплата

Итак, делая DumpHeap -MT для этого типа, я получаю стек ссылок на объекты. Выбрав случайное число из них, я делаю! Gcroot, и команда возвращается, сообщая, что на нее не содержится никаких ссылок.

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

Кто-нибудь может объяснить, что может происходить?

Ответы [ 7 ]

4 голосов
/ 08 марта 2009

Вы можете попробовать использовать sosex.dll в Windbg, который является расширением, написанным для помощи в отладке .NET. Существует команда с именем! Refs, похожая на! Gcroot, в которой она покажет вам все объекты, ссылающиеся на объект, плюс она покажет все объекты, на которые она тоже ссылается.

В примере на сайте автора! Refs используется против объекта, и результат выглядит следующим образом:

0:000> !refs 0000000080000db8
Objects referenced by 0000000080000db8 (System.Threading.Mutex):
0000000080000ef0         32    Microsoft.Win32.SafeHandles.SafeWaitHandle 

Objects referencing 0000000080000db8 (System.Threading.Mutex):
0000000080000e08         72    System.Threading.Mutex+<>c__DisplayClass3
0000000080000e50         64    System.Runtime.CompilerServices.RuntimeHelpers+CleanupCode
2 голосов
/ 14 августа 2009

Может ли PaymentObject реализовать финализатор случайно? Вызывает ли это STA COM-объект?

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

generation 0 has 57 finalizable objects (0409b5cc->0409b6b0)
generation 1 has 55 finalizable objects (0409b4f0->0409b5cc)
generation 2 has 0 finalizable objects (0409b4f0->0409b4f0)
Ready for finalization 0 objects (0409b6b0->0409b6b0)

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

Ошибка в финализаторе может заблокировать поток финализатора и предотвратить сбор объектов.

Если объект PaymentOption вызывает устаревший COM-объект STA, то эта статья Исключения ASP.NET Hang и OutOfMemory, вызванные компонентами STA , могут указывать в правильном направлении.

2 голосов
/ 02 марта 2009

Мало вещей:

  1. GC.Collect не поможет вам в отладке. Сборщик мусора уже вызывается: если бы какие-либо объекты были доступны для сбора, это уже произошло бы.
  2. Неиспользуемая память на сервере тратится впустую. Вы уверены, что память «просочилась», или просто фреймворк решает, что может сохранить больше вещей в памяти или сохранить больше памяти для быстрого доступа? В этом случае я подозреваю, что у вас утечка памяти, но это нужно проверить дважды.
  3. Звучит так, будто вы не ожидаете сохранения ссылки на объекты PaymentOption. Возможно статическая коллекция где-нибудь? Или отдельная тема?
1 голос
/ 28 июля 2009

Я сам исследовал ту же проблему и спрашивал, почему не собирались объекты, на которые не было ссылок.

Объекты размером более 85 000 байт хранятся в куче больших объектов, из которой память освобождается реже.

http://msdn.microsoft.com/en-us/magazine/cc534993.aspx

Отдельная опция PaymentOption может быть не такой большой, но содержится ли она в коллекциях или основана на чем-то вроде DataSet? Вам нужно выбрать несколько экземпляров PaymentOption / collection / DataSet, а затем использовать команду sos! Objsize, чтобы увидеть, насколько они велики.

К сожалению, это на самом деле не отвечает на вопрос. Мне нравится думать, что я могу доверять .net Framework заботиться о высвобождении неиспользуемой памяти всякий раз, когда это необходимо. Однако я вижу, что рабочим процессом, выполняющим приложение, на которое я смотрю, используется много памяти, даже если память на сервере выглядит довольно плотно.

1 голос
/ 02 марта 2009

Случайно ли создан объект PaymentOption в асинхронном процессе? Я кое-что помню о том, что если вы не позвоните в EndInvoke, у вас могут возникнуть такие проблемы.

1 голос
/ 02 марта 2009

Не без дополнительной информации о вашем заявлении. Но мы столкнулись с некоторыми неприятными проблемами с памятью давным-давно. Используете ли вы кэширование ASP.NET? Как любит говорить Раймонд Чен, «плохая стратегия кэширования неотличима от утечки памяти».

Проверьте другой инструмент - CLRProfiler.exe - он поможет вам пройти по деревьям ссылок на объекты, чтобы увидеть, где находятся ваши объекты. Это тоже хорошо: текст ссылки

Вы слышали это раньше - если вам нужно GC.Collect, что-то не так.

0 голосов
/ 02 марта 2010

К вашему сведению, SOS в .NET 4 поддерживает несколько новых команд, которые могут оказаться полезными, а именно: !gcwhere (найти генерацию возражения; gcgen sosex) и !findroots (делает то, что говорит на жестяной коробке; sosex's ! рефов)

Оба документа описаны в документации SOS и , упомянутой в блоге Тесс Феррандез .

...