内存碎片?

时间:2013-08-13 10:19:18

标签: c# asp.net-mvc-4 windbg memory-dump

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

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

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

  1. 1.70GB,292MB
  2. 2.03GB,337MB
  3. 2.55GB,347MB
  4. 因此,您看到托管堆的增长速度不如转储文件。 当我执行dumpheap -stat时,我发现Free对象使用了大部分空间(下面是每个转储文件)

    1. 147MB
    2. 145MB
    3. 213MB
    4. 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没有显示它们。

      enter image description here

      red line   - user load
      green line - bytes in all heaps
      blue line  - pinned objects
      

      EDIT2: 添加大于0.5 MB的碎片块:从!dumpheap -stat

      输出

1 个答案:

答案 0 :(得分:2)

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

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