Я не уверен, потому что у меня нет большого опыта в анализе дампов памяти, но я думаю, что у нас могут быть проблемы с фрагментацией памяти.
Во время нагрузочных тестов мы видим, что использование памяти растет до точки перезапуска приложения. Это приложение ASP.NET MVC 4 на 64-битной машине. Я не участвовал в написании этого. Меня просто попросили попробовать проанализировать дампы памяти.
Итак, во время последнего нагрузочного теста мы создали 3 дампа памяти (ниже их размеров и общего размера кучи GC, выводимого из eeheap -gc):
- 1.70GB, 292MB
- 2.03GB, 337MB
- 2.55GB, 347MB
Итак, как видите, управляемая куча не растет так сильно, как файлы дампа. Когда я делаю dumpheap -stat, я вижу, что больше всего места используется бесплатными объектами (ниже для каждого файла дампа)
- 147MB
- 145MB
- 213MB
Fragmented blocks larger than 0.5 MB: Addr Size Followed by 000000bcc668e0a8 0.7MB 000000bcc6738650 System.Object[] 000000bcc6949f88 4.4MB 000000bcc6dab820 System.Collections.Specialized.NameObjectCollectionBase+NameObjectEntry 000000bd4626c4b8 0.7MB 000000bd463165f8 System.Byte[] 000000bd463fcc48 51.5MB 000000bd4977baf0 System.Threading.ThreadStart 000000be463600c8 0.7MB 000000be464108f0 Free 000000bec67e50e0 1.1MB 000000bec690b020 System.Collections.Generic.List`1[[OurType, ANotherOurType]] 000000bec690b0b8 3.2MB 000000bec6c3b170 System.Byte[] 000000bfc6605e00 1.0MB 000000bfc6710190 Free 000000bfc6743c58 32.8MB 000000bfc8806fe8 System.Threading.ExecutionContext 000000c046200580 1.0MB 000000c0462ff2a0 SomeOurType 000000c0463a1270 3.6MB 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
Handles: Strong Handles: 154 Pinned Handles: 23 Ref Count Handles: 2 Weak Long Handles: 1794 Weak Short Handles: 74 SizedRef Handles: 17 Dependent Handles: 1
Не знаю, что еще можно проверить. У нас проблема фрагментации памяти? Вы можете указать мне какое-нибудь направление?
Изменить: я прикрепляю счетчики производительности, собранные во время нагрузочного теста. Странно, потому что он показывает много закрепленных объектов, но! Gchandles их не показывает.
red line - user load green line - bytes in all heaps blue line - pinned objects
Edit2: добавлены фрагментированные блоки размером более 0,5 МБ: вывод из! Dumpheap -stat