Большой необъяснимый объем памяти в дампе памяти процесса .NET - PullRequest
0 голосов
/ 17 ноября 2018

Я не могу объяснить большую часть памяти, используемой процессом C #. Общий объем памяти составляет 10 ГБ, но общий объем достижимых и недоступных объектов составляет всего 2,5 ГБ. Интересно, что это были за 7,5 ГБ?

Я ищу наиболее вероятные объяснения или способ выяснить, что это за память.

Вот точная ситуация. Процесс .NET 4.5.1. Он загружает страницы из Интернета и обрабатывает их с помощью машинного обучения. Как показывает VMMap, память почти полностью находится в управляемой куче. Это, кажется, исключает неуправляемую утечку памяти. enter image description here

Процесс работал в течение нескольких дней, и память медленно росла. В какой-то момент объем памяти составляет 11 ГБ. Я прекращаю все, что работает в процессе. Я запускаю сборки мусора, включая сжатие кучи больших объектов несколько раз (с интервалом в одну минуту):

GCSettings.LargeObjectHeapCompactionMode = GCLargeObjectHeapCompactionMode.CompactOnce;
GC.Collect();

Память уменьшается до 10 ГБ. Затем я создаю дамп:

procdump -ma psid

Дамп составляет 10 ГБ, как и ожидалось.

Я открываю дамп с помощью .NET memory profiler (версия 5.6). Дамп отображает 2,2 ГБ доступных объектов и 0,3 ГБ недоступных объектов. Чем можно объяснить оставшиеся 7,5 ГБ?

Возможные объяснения, о которых я думал:

  • LOH на самом деле не полностью уплотняется
  • некоторая память используется вне объектов, отображаемых профилировщиком

1 Ответ

0 голосов
/ 19 ноября 2018

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

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

!dumpheap -stat

Затем я посмотрел на раздел «Фрагментированные блоки больше ...».WinDbg говорит, что объекты лежат между свободными блоками, что делает уплотнение невозможным.Затем я посмотрел на то, что удерживает эти объекты, и, если они закреплены, вот, например, объект по адресу 0000000bfaf93b80:

!gcroot 0000000bfaf93b80

Отображается граф ссылок:

00000004082945e0 (async pinned handle)
-> 0000000535b3a3e0 System.Threading.OverlappedData
-> 00000006f5266d38 System.Threading.IOCompletionCallback
-> 0000000b35402220 System.Net.Sockets.SocketAsyncEventArgs
-> 0000000bf578c850 System.Net.Sockets.Socket
-> 0000000bf578c900 System.Net.SocketAddress
-> 0000000bfaf93b80 System.Byte[]

00000004082e2148 (pinned handle)
-> 0000000bfaf93b80 System.Byte[]

Последние двалинии говорят вам, что объект закреплен.

Закрепленные объекты - это буферы, которые невозможно переместить, поскольку их адрес используется совместно с неуправляемым кодом.Здесь вы можете догадаться, что это системный уровень TCP.Когда управляемому коду необходимо отправить адрес буфера во внешний код, ему нужно «закрепить» буфер, чтобы адрес оставался действительным: ГХ не может его переместить.

Эти буферы, хотя и очень малыЧасть памяти делает уплотнение невозможным и, таким образом, вызывает большую «утечку» памяти, даже если это не совсем утечка, а скорее проблема фрагментации.Это может произойти на LOH или на кучах поколений точно так же.Теперь вопрос: что заставляет эти закрепленные объекты жить вечно: найдите основную причину утечки, которая вызывает фрагментацию.

Подобные вопросы можно прочитать здесь:

Примечание: основная причина была в сторонней библиотеке AerospikeClient с использованием .NET async Socket API, который известен тем, что закрепляет отправленные ему буферы .Хотя AerospikeClient правильно использовал буферный пул, буферный пул был воссоздан при повторном создании их клиента.Поскольку мы воссоздали их клиента каждый час, а не создавали один навсегда, пул буферов был воссоздан, что привело к увеличению числа закрепленных буферов, что, в свою очередь, привело к неограниченной фрагментации.Что остается неясным, так это то, почему старые буферы никогда не открепляются, когда передача завершена или, по крайней мере, когда их клиент удален.

...