Как я могу определить нежелательные объекты .NET, которые не собираются мусором? - PullRequest
6 голосов
/ 02 декабря 2011

Мое приложение (C # .NET 4.0) работает в течение нескольких дней, обновляя смоделированную учетную запись в соответствии с изменениями цен, полученными из базы данных SQLite.

Все, что мне нужно на конкретную дату, - это учетная запись в ее текущем состоянии и последние цены. Я ожидаю, что сборщик мусора сохранит использование памяти на довольно ровном уровне: я вижу постоянное увеличение рабочего набора и частной памяти (как сообщает System.Diagnostics.GetCurrentProcess()), а также GC.GetTotalMemory(true): около 300 КБ. в день в этом случае. Неизбежно, все это рушится примерно через 12 лет моделирования, после чего использование памяти увеличилось примерно на 1 ГБ.

Использование памяти увеличивается более или менее линейно (гораздо более плавно, если я нажимаю GC.Collect() в конце каждого дня).

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

Что я мог бы попытаться определить, где мне непреднамеренно удалось создать такую ​​ситуацию?

Я скачал и запустил CLRProfiler - тем не менее, большую часть выходных уйдет на то, чтобы переварить документацию, и нет никаких гарантий, что он сможет помочь.

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

ПРИМЕЧАНИЕ. Проблема не связана с событием, и в ней нет графического компонента.

Ответы [ 3 ]

7 голосов
/ 02 декабря 2011

Вы сказали, что можете смоделировать рабочую нагрузку, чтобы вызвать сбой приложения.Чтобы быстро найти утечку, смоделируйте рабочую нагрузку, пока потребление памяти не станет значительным (например, 100 МБ), подключите WinDbg или VS с неуправляемой отладкой к вашему процессу и запустите в немедленном окне:

.load sos
extension C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\sos.dll loaded
!dumpheap -stat
total 2885 objects
Statistics:
MT    Count    TotalSize Class Name
7a5eab18        1           12 System.Diagnostics.TraceOptions
(lots of unimportant stuff here)
79332b54      304         7296 System.Collections.ArrayList
79333274       56        11640 System.Collections.Hashtable+bucket[]
793042f4      345        50056 System.Object[]
79330b24     1041        99428 System.String
79332cc0       21    107109728 System.Int32[]

Из этого (отсортированного) выводаВы можете сказать, что у вас проблема с типом int[].Тип:

!DumpHeap -type System.Int32[] (or whichever type you got)
Address       MT     Size
01381a1c 7931e9bc       40     
(cut)
075d1000 79332cc0 67108880     
03811000 79332cc0 40000016     
total 22 objects
Statistics:
MT    Count    TotalSize Class Name
7931e9bc        1           40 System.Int32[][]
79332cc0       21    107109728 System.Int32[]
Total 22 objects

Теперь у вас есть адрес вашего объекта (ов).Выберите один из них и запустите

!GCRoot 075d1000

И вы получите причину своей утечки.Кроме того, вы можете обратиться к этому руководству .

3 голосов
/ 02 декабря 2011

Используете ли вы события?Если объект A подписан на событие объекта B, то B сохраняет ссылку на A.Поэтому A нельзя собирать, пока B не удастся собрать.Если A отписывается от B, то ссылка B на A удаляется.

2 голосов
/ 02 декабря 2011

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

Редактировать: за это стоит попробовать Ants Memory Profiler . Я не знаю, как он сравнивается с тем, на который ты смотришь, но, попробовав его, кривая обучения на нем не так уж плоха, так что ты мог бы потратить меньше времени на его выяснение.

...