查找内存泄漏

时间:2017-06-26 12:22:51

标签: c# asp.net-mvc iis memory-management memory-leaks

我有一个Web应用程序,我使用很多不同的第三方组件,CMS,当然还有我的代码。出于某种原因,我的内存异常。

  

脚本抛出异常:内存不足

我试图找出发生了什么。这就是我发现的:

  • 我用50个线程运行测试,调用我的web应用程序的15个页面。记忆似乎很好。 IIS进程仅使用400 MB的RAM

  • 我在web.config中添加了一个空格,突然间我的IIS进程在30分钟内开始增长到超过GB。 Visual Studio无法拍摄我的记忆快照,因为它太大了(真的吗?!)所以我已经安装了ANTS内存分析器,但它说我的应用程序只使用了大约300 MB ANTS only 300 MB

IIS进程需要1 GB   [1]: https://i.stack.imgur.com/Ig8 pY.png

几分钟后我停止了测试,但内存没有释放。

(ANTS探测器停止工作,所以我重启了它) 422MB after release IIS 1.2GB Summary 4MB of strings

看起来应用程序似乎正在使用100-200MB内存,我正在为控制器使用输出缓存。我不明白的是,IIS消耗的内存一直在增长,出现了什么问题

更新

我的应用程序已自动重启,W3WP崩溃导致IIS释放内存,而我的压力暂时没有运行:

  

应用程序:w3wp.exe   框架版本:v4.0.30319   描述:由于.NET运行时在IP 5A3A86F1(5A0F0000)中出现内部错误,退出代码为80131506,该进程终止。

  

错误应用程序名称:w3wp.exe,版本:10.0.15063.0,时间戳:0xacce422f   错误模块名称:clr.dll,版本:4.7.2098.0,时间戳:0x59028d36   异常代码:0xc0000005   故障偏移:0x002b86f1   错误进程id:0x50a4   错误应用程序启动时间:0x01d2ee688f323893   错误的应用程序路径:C:\ WINDOWS \ SysWOW64 \ inetsrv \ w3wp.exe   错误模块路径:C:\ Windows \ Microsoft.NET \ Framework \ v4.0.30319 \ clr.dll   报告编号:4362ddc5-f8d7-4441-8916-3830f9268b3a   错误包全名:   错误的包相关应用程序ID:

enter image description here

更新2

我运行了DebugDiag并且我对该网站进行了压力测试,直到它消耗了大约3.5 GB的RAM。

enter image description here

Chakra是微软的图书馆。

enter image description here enter image description here

所以现在我有两个问题。

  1. 是ChakraCore有泄漏还是正在使用/分配它?如何定义哪个库?
  2. 2-它说27,000个分配。这是否意味着内存中仍有27,000个或者其中一些可能被分配然后处理?

    3-它仍然没有告诉我任何有关剩余的3GB消耗RAM的信息。它总共只有600 MB(私有+虚拟)。

4 个答案:

答案 0 :(得分:4)

在您的分析中,我发现.net分析没有正确完成。您是否在捕获内存转储的同一台机器上进行分析?

  

要使debugdiag正常工作,您必须具有相同的版本   安装在分析机器上的.net框架(应用程序)   同样。

另外请不要像this那样进行本机内存泄漏转储,除非它没有计算出非托管泄漏。从您的分析来看,这似乎是托管泄漏。

  

更改web.config文件时,会导致应用程序域   卸载和重新加载

让我们一步一步来做

  1. 使用DebugDiag(捕获连续的挂起转储)
    • 启动 DebugDiag集合并转到“进程”选项卡 debugdiag process tab
    • 开始压力测试
    • 检查内存使用情况,一旦达到1 GB,捕获挂起转储
      • 右键单击w3wp.exe进程
      • 选择Create Full Memory dump选项 capture full memory hang dump
    • 以2 GB和3.5 GB
    • 捕获另一个转储
    • 您应该在文件夹C:\ ProgramFiles \ DebugDiag \ Logs \ Misc \
    • 中捕获转储
    • 右键单击转储文件,然后选择Analyze .NET Memory Issue选项 Analyse .net memory issue
  2.   

    现在比较每个转储文件(1 GB,2 GB,3.5 GB)的分析   应该告诉你哪些.NET对象正在增加而没有得到   垃圾收集。

    在内存分析中,您应该看到 CLR信息****,.NET GC堆信息大多数内存消耗.NET对象等,如下所示。如果您的.net符号通过debugdiag分析正确识别

    ,则会出现这种情况
    CLR Information
     CLR version = 4.6.1648.0
     Microsoft.Diagnostics.Runtime version = 0.9.2.0
    .NET GC Heap Information
    Number of GC Heaps: 4 
    Heap Size 0x4001ce8 (67,116,264) 
    Heap Size 0x3d5cca0 (64,343,200) 
    Heap Size 0x3f8b0d0 (66,629,840) 
    Heap Size 0x3ccb0d0 (63,746,256) 
    GC Heap Size 249.71 MBytes  
    Total Commit Size  249 MB 
    Total Reserved Size    17158 MB 
    
    40 most memory consuming .NET object types
    
    System.Char[]   193.01 MBytes    (12450 objects )
    Free      45.21 MBytes    (4760 objects )
    System.String      1.56 MBytes    (18072 objects ) 
    ==============trimmed out =======================
    

    DebugDaig自动分析应该给出以下

    1. **错误或警告** - 密切注意报告顶部的debugdiag分析显示的警告或错误。
    2. .NET GC堆信息 - 总提交大小 - 这大致等于您的.net内存使用量。
    3. 40大多数消耗.NET对象类型的内存 - 这可以用来比较连续转储中的内存增加。这将告诉你哪些对象导致了问题。有些时候你根本就没有使用的某些对象会来,可能来自某个第三方库。或者你会看到你自己创建的对象
    4. 终结器队列中的热门对象 - 如果您的终结器可能被阻止,这将为您提供任何线索。对象。我们讨论了类似的问题herehere
    5. 大对象堆上的对象 - 这会导致内存碎片和大对象堆容器对象的大小超过85K。
    6. 缓存,数据表,应用程序域,动态程序集等的大小。在一个过程中拥有大量应用程序域并不是一个好主意
    7. 请注意,有时debugdiag自动分析无法找出根本原因并需要使用windbg进行手动分析。 DebugDiag分析,请参阅此video

      希望这有帮助!

答案 1 :(得分:1)

由于看起来你可以重现你的问题,有时最简单的方法是删除你认为可能是根本原因的东西,然后重新测试(除非你需要很多时间来看它是否增长很多?)

在某些时候,错误将停止发生,你将知道代码的负责人。

但是,根据您的代码库,删除代码并不总是很容易,但仍然可以测试(即不会导致应用程序崩溃)。

答案 2 :(得分:1)

在修复内存泄漏方面,有两个步骤。

  1. 查找内存泄漏的位置。
  2. 修复内存泄漏。
  3. 通常第一步很棘手。因此,我建议继续使用ANTS内存分析器,首先找到正在增长的确切实例

    Profiling an ASP.NET application on IIS

    在您的问题中,您已经显示了类列表结果,其中甚至包括具有系统命名空间的类。要清除噪音,您可以选择“仅显示带来源的类”选项。

    enter image description here

    然后按照以下步骤进行操作。

    1. 在执行任何操作之前拍摄基本快照。
    2. 执行您怀疑有内存泄漏的操作。
    3. 拍摄更多快照,直到获得相当稳定的快照。
    4. 将最后一个快照与基础进行比较,看看哪些实例正在增长。

答案 3 :(得分:0)

你提到“我在web.config中添加了一个空格,突然间我的IIS进程在30分钟内开始增长到超过GB”。您在哪个web.config标记中添加了此空格。您的代码的哪一部分使用它。您的代码部分是否无法处理某些异常而不会导致内存泄漏。使用PerfView(转储GC堆)来分析转储。这可以准确地说明,占据这么多内存的对象是什么。在旧版本的.net中,它将是大对象堆(大数组)上的对象,或者是打开和错误处理的数据库连接和文件。

https://channel9.msdn.com/Series/PerfView-Tutorial/Tutorial-10-Investigating-NET-Heap-Memory-Leaks-Part1-Collecting-the-data

https://channel9.msdn.com/Series/PerfView-Tutorial/Tutorial-11-Investigating-NET-Heap-Memory-Leaks-Part2-Analyzing-the-data