2014-09-04 1 views
2

Я изучаю проблему с большим объемом памяти с моим приложением. Память продолжает расти, и я хотел бы узнать, где потребляется вся память. У меня есть файл дампа размером ~ 3 ГБ.Учет размера управляемой кучи и всех объектов в нем

Вот выход команды dumpheap -stat. Общий список длинный, но я просто хотел показать вам самые большие предметы, такие как byte [] (195 МБ), IdentifierChangedEventHandler (120 МБ), строки (119 МБ). Все это не суммирует, где близко к 3 ГБ.

000007fe94169ff0 101326  7295472 System.Linq.Enumerable+WhereListIterator`1[[CommonServices.WindowsEvent.EventIDExpression+RangeExpressionCollection+RangeExpression, CommonServices]] 
000007fe94237f08  1  7786800 System.Collections.Generic.Dictionary`2+Entry[[System.Int32, mscorlib],[OrderingServices.LocalCache, OrderingServices]][] 
000007fef1afc3a8 202112  8084480 System.Collections.Generic.List`1[[System.Guid, mscorlib]] 
000007fef1ac24c0 204144  9798912 System.Collections.ArrayList+ArrayListEnumeratorSimple 
000007fef1accc50 313792  10041344 System.Guid 
000007fef1ad14a0 314054  10049728 System.Security.SecureString 
000007fef1ac7790 131954  11403930 System.Char[] 
000007feed2f93b8  2063  11898472 System.Data.RBTree`1+Node[[System.Data.DataRow, System.Data]][] 
000007fef1a87890 316978  12679120 System.Security.SafeBSTRHandle 
000007fef1acc590 350337  14013480 System.Collections.ArrayList 
000007fe936bdcd0 202083  14549976 OrderingServices.LocalCache 
000007fe942db718 202083  16166640 System.Collections.Generic.Dictionary`2[[System.Guid, mscorlib],[System.Collections.Generic.HashSet`1[[System.Int32, mscorlib]], System.Core]] 
000007feed2f5910 248683  23873568 System.Data.DataRow 
000007fef1aca708 317533  25402640 System.Collections.Hashtable 
000007fe942dbf60 202021  32610456 System.Collections.Generic.Dictionary`2+Entry[[System.Guid, mscorlib],[System.Collections.Generic.HashSet`1[[System.Int32, mscorlib]], System.Core]][] 
000007fef1ac3838 319558  32975376 System.Collections.Hashtable+bucket[] 
000007fef1a74458 307557  35724224 System.Object[] 
000007feef6cc770 631242  38621784 System.Collections.Generic.HashSet`1+Slot[[System.Int32, mscorlib]][] 
000007feef6cb860 631242  40399488 System.Collections.Generic.HashSet`1[[System.Int32, mscorlib]] 
000007fef1ac9258 937270  48016624 System.Int32[] 
000007fef1ac6508 879690 119968068 System.String 
000007fef1aca690 176907 196509678 System.Byte[] 
00000000002ae930 139663 520724414  Free 
Total 14024120 objects 
Fragmented blocks larger than 0.5 MB: 
      Addr  Size  Followed by 
000000008e84f490 1.6MB 000000008e9f08b8 Microsoft.Win32.SafeHandles.SafeTokenHandle 
00000001878e1ca8 0.7MB 000000018798ffd8 Microsoft.Win32.SafeHandles.SafeTokenHandle 
0000000187ac1070 0.7MB 0000000187b76138 System.Threading.ReaderWriterLock 
0000000187d39d88 1.5MB 0000000187ec2788 System.Threading.ReaderWriterLock 
0000000187f7bfe0 0.9MB 000000018805ce90 System.Threading.ReaderWriterLock 
0000000188ad1b30 0.5MB 0000000188b5a190 System.Net.ListenerAsyncResult 
000000018909ef98 1.0MB 00000001891a9e90 System.Net.Sockets.Socket 
0000000189377440 0.6MB 0000000189417088 Microsoft.Win32.SafeHandles.SafeTokenHandle 
000000018a07e428 0.7MB 000000018a1382a0 System.Threading.ExecutionContext 
000000018a599610 1.2MB 000000018a6d4b50 Microsoft.Win32.SafeHandles.SafeTokenHandle 
000000018bad8b30 0.7MB 000000018bb87b00 Microsoft.Win32.SafeHandles.SafeTokenHandle 
000000018bb88778 1.1MB 000000018bcac050 System.Threading.ReaderWriterLock 
000000018bcac618 1.3MB 000000018bdee998 Microsoft.Win32.SafeHandles.SafeTokenHandle 
000000018ed68b78 1.0MB 000000018ee6c290 System.Threading.ReaderWriterLock 
000000018eec5b70 0.9MB 000000018efb37a8 System.Threading.ReaderWriterLock 
000000018f351930 0.7MB 000000018f40edb0 Microsoft.Win32.SafeHandles.SafeTokenHandle 
000000018f469d00 0.6MB 000000018f509360 System.Net.ListenerAsyncResult 
000000018f5508d8 2.8MB 000000018f824ad8 Microsoft.Win32.SafeHandles.SafeTokenHandle 
000000018f917610 2.2MB 000000018fb41790 Microsoft.Win32.SafeHandles.SafeTokenHandle 
000000028985e148 0.6MB 00000002898f72e0 System.Security.SafeBSTRHandle 
0000000289901008 0.8MB 00000002899c3138 System.Security.SafeBSTRHandle 
000000028a1e7378 0.7MB 000000028a295dd8 System.Net.ListenerAsyncResult 
000000028a56a8b8 1.3MB 000000028a6c23c8 System.Threading.ReaderWriterLock 
000000028a8c0a28 0.9MB 000000028a9b2b88 MonitoringServices.PerformanceCounter.PerformanceCounterDataPoint 
000000028b1b80c8 0.9MB 000000028b2a6a30 System.Data.SqlClient.SNIPacket 
000000028d37d7c0 0.6MB 000000028d4220f0 System.Transactions.SafeIUnknown 
000000028d5f05c8 1.6MB 000000028d789b20 System.Net.ListenerAsyncResult 
000000028d78ac08 2.4MB 000000028d9e7e58 System.Transactions.SafeIUnknown 
000000028d9ec618 0.7MB 000000028da95c88 System.Threading.ReaderWriterLock 
000000028daa5f58 1.2MB 000000028dbe2af8 System.Threading.ReaderWriterLock 
000000028dbe3b00 0.7MB 000000028dc98aa0 System.Threading.ReaderWriterLock 
000000028dc99aa8 1.6MB 000000028de30e40 System.String 
0000000385644a88 0.7MB 00000003856eee30 Microsoft.Win32.SafeHandles.SafeWaitHandle 
00000003868ecbc0 0.7MB 00000003869a18a8 System.Byte[] 
00000003878d0330 0.5MB 0000000387950678 System.Threading.ReaderWriterLock 
0000000387951680 1.2MB 0000000387a84b18 Microsoft.Win32.SafeHandles.SafeTokenHandle 
0000000387e137d0 1.8MB 0000000387fdbb50 System.Security.SafeBSTRHandle 
0000000388175388 1.5MB 00000003882ed100 System.Threading.ReaderWriterLock 
00000003882ee108 0.8MB 00000003883b5b10 System.String 
00000003883c5c20 0.9MB 00000003884aa8d8 System.Byte[] 
00000003891fa318 1.7MB 00000003893a3e30 Microsoft.Win32.SafeHandles.SafeTokenHandle 
0000000389cafe00 0.7MB 0000000389d61ff0 System.Byte[] 
000000038a036238 1.0MB 000000038a135428 System.Net.ListenerAsyncResult 

Здесь выведено! Address -summary. Резюме использования кучи, показывающее 1,1 ГБ, хотя я не знаю, все ли это управляемая куча?

0:000> !address -summary 
--- Usage Summary ---------------- RgnCount ----------- Total Size -------- %ofBusy %ofTotal 
Free         525  7fa`04208000 ( 7.977 Tb)   99.71% 
<unknown>        917  5`8f56a000 ( 22.240 Gb) 92.92% 0.27% 
Heap         204  0`4b5af000 ( 1.177 Gb) 4.92% 0.01% 
Image         2327  0`12fc5000 (303.770 Mb) 1.24% 0.00% 
Stack         701  0`0df80000 (223.500 Mb) 0.91% 0.00% 
TEB          229  0`001ca000 ( 1.789 Mb) 0.01% 0.00% 
Other         19  0`001bf000 ( 1.746 Mb) 0.01% 0.00% 
PEB          1  0`00001000 ( 4.000 kb) 0.00% 0.00% 

--- Type Summary (for busy) ------ RgnCount ----------- Total Size -------- %ofBusy %ofTotal 
MEM_PRIVATE       1717  5`e6543000 ( 23.599 Gb) 98.59% 0.29% 
MEM_IMAGE        2627  0`140dc000 (320.859 Mb) 1.31% 0.00% 
MEM_MAPPED        54  0`017c9000 ( 23.785 Mb) 0.10% 0.00% 

--- State Summary ---------------- RgnCount ----------- Total Size -------- %ofBusy %ofTotal 
MEM_FREE        525  7fa`04208000 ( 7.977 Tb)   99.71% 
MEM_RESERVE        736  5`2ba70000 ( 20.682 Gb) 86.41% 0.25% 
MEM_COMMIT        3662  0`d0378000 ( 3.253 Gb) 13.59% 0.04% 

--- Protect Summary (for commit) - RgnCount ----------- Total Size -------- %ofBusy %ofTotal 
PAGE_READWRITE       1590  0`babd4000 ( 2.918 Gb) 12.19% 0.04% 
PAGE_EXECUTE_READ      260  0`0f1ba000 (241.727 Mb) 0.99% 0.00% 
PAGE_READONLY       756  0`0376d000 ( 55.426 Mb) 0.23% 0.00% 
PAGE_WRITECOPY       561  0`01f24000 ( 31.141 Mb) 0.13% 0.00% 
PAGE_EXECUTE_READWRITE     180  0`008bd000 ( 8.738 Mb) 0.04% 0.00% 
PAGE_READWRITE|PAGE_GUARD    229  0`0043f000 ( 4.246 Mb) 0.02% 0.00% 
PAGE_EXECUTE_WRITECOPY     85  0`0025a000 ( 2.352 Mb) 0.01% 0.00% 
PAGE_EXECUTE        1  0`00003000 ( 12.000 kb) 0.00% 0.00% 

--- Largest Region by Usage ----------- Base Address -------- Region Size ---------- 
Free          5`ffff0000  7f8`93260000 ( 7.971 Tb) 
<unknown>         3`92f8f000  0`ed061000 ( 3.703 Gb) 
Heap          0`19010000  0`00fd0000 ( 15.813 Mb) 
Image         7fe`edfb9000  0`01368000 ( 19.406 Mb) 
Stack          0`0b8d0000  0`000fc000 (1008.000 kb) 
TEB          7ff`ffbd4000  0`00002000 ( 8.000 kb) 
Other          0`008a0000  0`00181000 ( 1.504 Mb) 
PEB          7ff`fffdf000  0`00001000 ( 4.000 kb) 

И наконец, если вы используете eeheap -gc, его показ ~ 1,6 ГБ во всех четырех кучах GC.

0:000> !EEHeap -gc 

Number of GC Heaps: 4 
------------------------------ 
Heap 0 (00000000002d8aa0) 
generation 0 starts at 0x000000008ff94830 
generation 1 starts at 0x000000008f1157e8 
generation 2 starts at 0x000000007fff1000 
ephemeral segment allocation context: none 
segment  begin allocated size 
000000007fff0000 000000007fff1000 00000000935cc580 0x135db580(324908416) 
Large object heap starts at 0x000000047fff1000 
segment  begin allocated size 
000000047fff0000 000000047fff1000 0000000484d38270 0x4d47270(81031792) 
Heap Size:    Size: 0x183227f0 (405940208) bytes. 
------------------------------ 
Heap 1 (0000000000abcf00) 
generation 0 starts at 0x0000000190b5f3f8 
generation 1 starts at 0x000000018fcb1988 
generation 2 starts at 0x000000017fff1000 
ephemeral segment allocation context: none 
segment  begin allocated size 
000000017fff0000 000000017fff1000 0000000193ee36f8 0x13ef26f8(334440184) 
Large object heap starts at 0x000000048fff1000 
segment  begin allocated size 
000000048fff0000 000000048fff1000 00000004960eae48 0x60f9e48(101686856) 
Heap Size:    Size: 0x19fec540 (436127040) bytes. 
------------------------------ 
Heap 2 (0000000000ac78b0) 
generation 0 starts at 0x000000028f89f588 
generation 1 starts at 0x000000028e83ca90 
generation 2 starts at 0x000000027fff1000 
ephemeral segment allocation context: none 
segment  begin allocated size 
000000027fff0000 000000027fff1000 0000000292bf43d0 0x12c033d0(314586064) 
Large object heap starts at 0x000000049fff1000 
segment  begin allocated size 
000000049fff0000 000000049fff1000 00000004a5b90b78 0x5b9fb78(96074616) 
Heap Size:    Size: 0x187a2f48 (410660680) bytes. 
------------------------------ 
Heap 3 (0000000000ad2c00) 
generation 0 starts at 0x000000038ecddd18 
generation 1 starts at 0x000000038dcb9ec8 
generation 2 starts at 0x000000037fff1000 
ephemeral segment allocation context: none 
segment  begin allocated size 
000000037fff0000 000000037fff1000 00000003925e93b8 0x125f83b8(308249528) 
Large object heap starts at 0x00000004afff1000 
segment  begin allocated size 
00000004afff0000 00000004afff1000 00000004b55a61e8 0x55b51e8(89870824) 
Heap Size:    Size: 0x17bad5a0 (398120352) bytes. 
------------------------------ 
GC Heap Size:   Size: 0x6265f218 (1650848280) bytes. 

У меня есть два вопроса.
1. Есть ли в любом случае получение суммы всех размеров объектов, перечисленных в команде! Dumpheap -stat.
2. Есть ли подтверждение того, что размер кучи GC совпадает с общим размером всех объектов из! Dumpheap -stat, чтобы я мог быть уверен, что все мои объекты учтены?

+0

Вы вызываете метод * Dispose() * для неуправляемых ресурсов (или, наоборот, просматриваете их внутри оператора * с помощью *)? –

+1

Windbg не очень подходит для достойного профилирования .NET. Но эй, обработчики событий на 120 мегабайт, больше не смотрите. Стандартным объяснением является связанный с WMI заторможенный поток финализатора. –

+0

Спасибо, Ханс. Как я могу исследовать его дальше. syncblk не отображает нити, которые ждут в других потоках –

ответ

2

Прежде всего, в address -summary показаны только кучи, созданные функцией CreateHeap(), которая не является .NET. .NET использует свои собственные кучи и отображается на выходе как <unknown>.

Далее вы забыли добавить «бесплатные» объекты размером 520 МБ. Это места в кучи .NET, где раньше был объект .NET, но затем был собран мусор. Это свободное место может быть возвращено или не возвращено ОС позже. Во время выполнения команды он использовался менеджером памяти .NET, но этот менеджер считал его бесплатным. С точки зрения OS эта память все еще используется (зарезервирована или установлена, но не бесплатна).

В-третьих, я предполагаю, что это ошибка: общий размер кучи GC составляет 1650848280, что составляет 1,6 ГБ, а не 160 ГБ. В противном случае это противоречило бы номеру <unknown>, который составляет 22 ГБ.

Один вопрос открыт, хотя: если <unknown> - 22 ГБ, но только 1,6 ГБ управляется .NET, остальные - другими компонентами, которые напрямую звонят по номеру VirtualAlloc(). Это довольно необычно, потому что зернистость VirtualAlloc() очень грубая, поэтому никто ее не использует. Может существовать прецедент, если вы знаете, что делаете с этими большими блоками памяти.

Что касается ваших вопросов: см. Ответ от @SteveJohnson.Я не подтверждаю, что фрагментация памяти вызвана тяжелыми асинхронными вводами-выводами. Это может быть одной из причин, но есть и другие, например. (обычно в сочетании с некоторыми родными материалами). Не забывайте различать фрагментацию кучи мелких объектов и фрагментацию кучи больших объектов.

Update:

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

.logopen virtualalloc.log 
bp Kernel32!VirtualAlloc ".echo ANALYZE>;k;.echo <ANALYZE;g" 
bp Kernel32!VirtualAllocEx ".echo ANALYZE>;k;.echo <ANALYZE;g" 
g 

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

Другой подход может быть Rohitab API monitor и фильтровать для VirtualAlloc. Вы найдете VirtualAlloc и VirtualAllocEx в System Servcies/Memory Management/Virtual Memory/Kernel32.dll. К сожалению, формат файла не открыт, поэтому вы не можете анализировать результаты с помощью инструмента.

+0

Спасибо. Вы правы, это 1,6 ГБ, я сделал исправление. Так что если 22GB - это управляемая куча и GC, занимающая только 1,6 ГБ, как я могу найти, какие объекты составляют остаток ~ 20 ГБ? –

+0

@PaulSnow: Не сказано, что есть объекты. В основном это всего лишь блок памяти (байт []), и любой, кто его попросит, может сделать с ним то, что он хочет. Я обновил свой ответ для возможного подхода к отладке этого в живой сессии. –

1

1 - нет, но вы можете приблизиться к этому! Sosex.dumpgen 0 -stat,! Sosex.dumpgen 1 -stat,! Sosex.dumpgen 2 -stat и! Sosex.dumpgen 3 -стат (это LOH). Каждая из этих команд даст вам общий размер всех объектов в каждом поколении.

2 - В настоящее время у меня нет отладчика, но я думаю, что если вы добавите все размеры сегмента от! Eeheap -gc, вы должны приблизиться к общему объему всех ваших объектов. ! sosex.dumpgen также дает вам общий размер поколения (размеры сегмента), поэтому он должен соответствовать тому, что вы видите с помощью eeheap -gc.

Похоже, что у вас есть тонна фрагментации кучи, как указано 520 724,414 байт свободных объектов. Это обычно вызвано тяжелым асинхронным вводом-выводом.

+0

Спасибо, я понял большое количество бесплатных объектов, но это будет проблемой только в том случае, если это в LOH. Я пытаюсь расследовать эту часть. Можете ли вы предоставить какие-либо ссылки о том, как тяжелый асинхронный ввод-вывод может способствовать фрагментации. –

+0

У меня нет ссылки, но в большинстве случаев фрагментации кучи, которую я отлаживал, виновником был асинхронный ввод-вывод. Когда вы передаете байт [] в метод асинхронного ввода-вывода, этот буфер должен быть закреплен перед его передачей в систему. Async I/O не является единственной причиной фрагментации кучи, но, как я уже сказал, это частая проблема в моем опыте. –

Смежные вопросы