Фрагментация памяти?

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

Во время нагрузочных тестов мы видим, что использование памяти растет до точки, где приложение перезапускается. Это приложение ASP.NET MVC 4 на 64-битной машине. Я не участвовал в написании этого. Меня просто попросили попробовать проанализировать дампы памяти.

Поэтому во время последнего нагрузочного теста мы создали 3 дампа памяти (ниже их размеров и общего размера кучи GC, выведенного из eeheap -gc):

  1. 1,70 ГБ, 292 МБ
  2. 2,03 ГБ, 337 МБ
  3. 2,55 ГБ, 347 МБ

Итак, как вы видите, управляемая куча не растет так же, как файлы дампа. Когда я делаю dumpheap -stat, я вижу, что большая часть пространства используется свободными объектами (ниже для каждого файла дампа)

  1. 147MB
  2. 145MB
  3. 213MB
Фрагментированные блоки размером более 0,5 МБ:
            Адреса Размер с последующим
000000bcc668e0a8    0,7 МБ 000000bcc6738650 System.Object[]
000000bcc6949f88    4.4MB 000000bcc6dab820 System.Collections.Specialized.NameObjectCollectionBase+NameObjectEntry
000000bd4626c4b8    0,7 МБ 000000bd463165f8 System.Byte[]
000000bd463fcc48   51,5 МБ 000000bd4977baf0 System.Threading.ThreadStart
000000be463600c8    0.7MB 000000be464108f0 Бесплатно
000000bec67e50e0    1,1 МБ 000000bec690b020 System.Collections.Generic.List`1[[OurType, ANotherOurType]]
000000bec690b0b8    3,2 МБ 000000bec6c3b170 System.Byte[]
000000bfc6605e00    1,0 МБ 000000bfc6710190 Бесплатно
000000bfc6743c58   32,8 МБ 000000bfc8806fe8 System.Threading.ExecutionContext
000000c046200580    1,0 МБ 000000c0462ff2a0 SomeOurType
000000c0463a1270    3,6 МБ 000000c046732ac0 Microsoft.Win32.SafeHandles.SafeCapiKeyHandle

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

Приложение использует две внешние библиотеки. Один для создания PDF-ов и другой для создания файлов штрих-кодов. Библиотека штрих-кодов генерирует AccessViolationException (примерно 70 раз за 2200 попыток). Это бросает с этой трассировкой стека

System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
   at System.Drawing.SafeNativeMethods.Gdip.IntGdipDeleteGraphics(HandleRef graphics)
   at System.Drawing.Graphics.Dispose(Boolean disposing)
   at System.Drawing.Graphics.Dispose()
   at Lesnikowski.Barcode.BaseBarcode.Render()
   at Lesnikowski.Barcode.BaseBarcode.Save(Stream stream, ImageType imageType)

Я читал, что фрагментация памяти часто вызывается закреплением памяти, но это вывод! Gchandles

Ручки:
    Сильные ручки:       154
    Закрепленные ручки:       23
    Ref Count Ручки: 2
    Слабые длинные ручки:    1794
    Слабые короткие ручки:   74
    Ручки SizedRef: 17
    Зависимые ручки: 1

Я не знаю, что еще я могу проверить. Есть ли у нас проблема фрагментации памяти? Можете ли вы указать мне в каком-то направлении?

Изменить: я прилагаю счетчики производительности, собранные во время нагрузочного теста. Странно, потому что это показывает много закрепленных объектов, но! Gchandles не показывали их.

введите описание изображения здесь

красная линия - пользовательская нагрузка
зеленая линия - байты во всех кучах
синяя линия - закрепленные объекты

Edit2: добавлены фрагментированные блоки размером более 0,5 МБ: вывод из! Dumpheap -stat

1 ответ

Вы должны использовать !address -summary чтобы получить представление об использовании виртуальной памяти в этом процессе. Даже при том, что, кажется, есть некоторая фрагментация кучи, вполне вероятно, что в вашем процессе есть какой-то дополнительный потребитель большой памяти Это может быть куча Win32, это могут быть стеки потоков, это могут быть сборки, которые вы загружаете динамически, и так далее.

Для каждого типа утечки вы должны будете следовать немного другому подходу. Для проверки кучи Win32, вы должны использовать варианты !heap команда - !heap -stat, !heap -s -h 0, Для проблем с загрузкой сборки, вы должны посмотреть на кучу загрузчика с !eeheap -loader а затем проверить различные домены приложений, которые у вас есть с !dumpdomain чтобы увидеть, какие сборки вы загружаете. Это только некоторые примеры - вам нужно будет предоставить более подробную информацию о вашей ситуации.

Другие вопросы по тегам