3

我不确定,因为我在分析内存转储方面没有太多经验,但我认为我们可能会遇到内存碎片问题。

在负载测试期间,我们看到内存使用量正在增长到应用程序重新启动的程度。它是 64 位机器上的 ASP.NET MVC 4 应用程序。我没有参与编写它。我只是被要求尝试分析内存转储。

因此,在上次负载测试期间,我们创建了 3 个内存转储(低于它们的大小和来自 eeheap -gc 的总 GC 堆大小输出):

  1. 1.70GB、292MB
  2. 2.03GB、337MB
  3. 2.55GB、347MB

因此,正如您所见,托管堆的增长速度不如转储文件。当我执行 dumpheap -stat 时,我看到大部分空间都被 Free 对象使用(下面是每个转储文件)

  1. 147MB
  2. 145MB
  3. 213MB
大于 0.5 MB 的碎片块:
            地址大小后跟
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 免费
000000bec67e50e0 1.1MB 000000bec690b020 System.Collections.Generic.List`1[[OurType, ANotherOurType]]
000000bec690b0b8 3.2MB 000000bec6c3b170 System.Byte[]
000000bfc6605e00 1.0MB 000000bfc6710190 免费
000000bfc6743c58 32.8MB 000000bfc8806fe8 System.Threading.ExecutionContext
000000c046200580 1.0MB 000000c0462ff2a0 SomeOurType
000000c0463a1270 3.6MB 000000c046732ac0 Microsoft.Win32.SafeHandles.SafeCapiKeyHandle

据我了解,当 Free 对象仅占所有堆大小的内存总量的一小部分时,这不是问题。这里看起来是个问题。

应用程序正在使用两个外部库。一种用于创建 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 输出

把手:
    强力手柄:154
    固定手柄:23
    参考计数句柄:2
    弱长手柄:1794
    弱短柄:74
    SizeRef 手柄:17
    从属句柄:1

我不知道我还能检查什么。我们有内存碎片问题吗?你能给我指出一些方向吗?

编辑:我附上了负载测试期间收集的性能计数器。很奇怪,因为它显示了很多固定的对象,但 !gchandles 没有显示它们。

在此处输入图像描述

红线 - 用户负载
绿线 - 所有堆中的字节
蓝线 - 固定对象

Edit2:添加了大于 0.5 MB 的碎片块:来自 !dumpheap -stat 的输出

4

1 回答 1

3

您应该使用!address -summary来了解此过程中的虚拟内存使用情况。尽管似乎存在一些堆碎片,但您的进程中很可能存在一些额外的大量内存消耗。它可能是 Win32 堆,可能是线程堆栈,也可能是动态加载的程序集,等等。

对于每种类型的泄漏,您必须遵循稍微不同的方法。对于 Win32 堆检查,您应该使用!heap命令的变体 - !heap -stat, !heap -s -h 0. 对于程序集加载问题,您应该查看加载程序堆,!eeheap -loader然后检查您拥有的各种 AppDomain!dumpdomain以查看您正在加载哪些程序集。这些只是一些示例 - 您必须提供有关您的情况的更多详细信息。

于 2013-08-21T22:49:28.910 回答