Профилирование LOH говорит, что корневые объекты GC (System.Object) являются источником утечки памяти - PullRequest
3 голосов
/ 16 мая 2011

У меня есть HttpHandler, который часто вызывается.Он использует Entity Framework для выполнения своей задачи.

Медленное увеличение используемой памяти на w3p.exe этого веб-приложения (у него есть отдельный пул приложений).Я использовал ANTS memory profiler и там много свободной памяти (LOH).ANTS говорит, что это GC root объекты.Я проверил свой код и есть несколько int и string, которые не могут привести к LOH!

Я проследил источник утечки, но, к сожалению, он имеет тип System.Object с большим количеством null свойства.Также есть LinkedList, некоторые HashTable s и WeakHashTable.

Как мне найти этот объект и исправить LOH?Как насчет возврата true для IsReusable из HttpHandler?

1 Ответ

1 голос
/ 02 октября 2012

Перво-наперво, вы должны отследить, что на самом деле происходит.В подобных ситуациях мой первый инструмент - всегда WinDbg.

http://www.windbg.org/ http://en.wikipedia.org/wiki/WinDbg

Чтобы использовать его с кодом управляемого / .NET, вам потребуетсяиспользовать расширение SOS (Son of Strike):

http://msdn.microsoft.com/en-us/library/bb190764.aspx

http://blogs.msdn.com/b/johan/archive/2007/11/13/getting-started-with-windbg-part-i.aspx

Итак, как только вы подключили WinDbg к процессу w3wp.exe,Первое, что вы захотите сделать, это выяснить, что на самом деле находится в ваших кучах:

!dumpheap -stat

Это даст вам красиво отформатированное представление всех текущих «живых» объектов в памяти, а также сколькоиз них есть, сколько байтов они занимают, сгруппированные по типу объекта.

Теперь, куча больших объектов (LOH) - так обычно, когда объекты собирают мусор, происходит сжатие, вроде какдефрагментация жесткого диска.Это позволяет быстро и эффективно распределять новые объекты.Проблема в том, что крупные объекты нелегко сжать - все должно двигаться, чтобы вместить их.Таким образом, все, что занимает более 85000 байт, застревает в специальном месте, называемом кучей больших объектов.Эта куча НЕ сжимается, поэтому со временем, подобно жесткому диску, происходит фрагментация, оставляя неиспользуемые пробелы в куче, что приводит к тому, что среде выполнения требуется больше места и т. Д., И т. Д.

Итак, давайте спросим windbgчтобы сказать нам, что находится в LOH:

!dumpheap -stat -min 85000

Это покажет вам, что на самом деле находится в куче больших объектов - некоторые из этих объектов могут выпрыгнуть прямо на вас, например, List или MyClass [],

ВАЖНО: Если вещи, которые вы видите в куче больших объектов, являются преднамеренно долгоживущими (как, например, статический экземпляр регистратора), это, вероятно, на самом деле не проблема.Однако вы хотите попытаться уменьшить количество недолговечных / часто создаваемых объектов, чтобы уменьшить фрагментацию.

Итак, я рекомендую шпаргалку для исследования SOS:

http://windbg.info/doc/1-common-cmds.html

http://windbg.info/doc/2-windbg-a-z.html

Забавные команды:

!gcroot <address>   <- will show you what object is "rooting" another
!CLRStack           <- show current managed call stack
!dumpobj <address>  <- show information about object at address

Но мой самый любимый из всех:

bp clr!SVR::gc_heap::allocate_large_object "!CLRStack; g;"

Который устанавливаетточка останова на фактическом внутреннем вызове, который CLR использует при выделении объекта в куче больших объектов, который при попадании выгрузит полную трассировку стека, а затем продолжит работу.

...