我不确定,因为我在分析内存转储方面没有太多经验,但我认为我们可能会遇到内存碎片问题。
在负载测试期间,我们发现内存使用量正在增长到应用程序重新启动的程度。 它是64位机器上的ASP.NET MVC 4应用程序。我没有参与写作。我被要求尝试分析内存转储。
因此,在上次负载测试期间,我们创建了3个内存转储(低于它们的大小和eeheap -gc输出的总GC堆大小):
因此,您看到托管堆的增长速度不如转储文件。 当我执行dumpheap -stat时,我发现Free对象使用了大部分空间(下面是每个转储文件)
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
根据我的理解,当Free对象只是所有堆大小的总内存量的一小部分时,这不是问题。这看起来像是一个问题。
App正在使用两个外部库。一个用于创建PDF-s和其他用于创建条形码文件。条形码库抛出了AccessViolationException(2200次尝试大约70次)。它抛出了这个堆栈跟踪
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 MB的碎片块:从!dumpheap -stat
输出答案 0 :(得分:2)
您应该使用!address -summary
来了解此过程中的虚拟内存使用情况。尽管似乎存在一些堆碎片,但在您的过程中很可能会有一些额外的大量内存使用者。它可能是Win32堆,可能是线程堆栈,也可能是动态加载的程序集,等等。
对于每种类型的泄漏,您必须遵循稍微不同的方法。对于Win32堆检查,您应该使用!heap
命令的变体 - !heap -stat
,!heap -s -h 0
。对于程序集加载问题,您应该使用!eeheap -loader
查看加载程序堆,然后检查使用!dumpdomain
的各种AppDomain以查看要加载的程序集。这些只是一些例子 - 您必须提供有关您的情况的更多详细信息。