发现内存泄漏

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

脚本抛出exception:内存不足

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

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

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

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

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

(ANTS探测器停止工作,所以我重新启动它) 发布后422MB IIS 1.2GB 摘要 4MB的字符串

它似乎并不是应用程序特别使用100-200MB内存,我正在为我的控制器使用输出缓存。 我不明白的是,为什么IIS消耗的内存一直在增长,哪些是错的

更新

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

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

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

在此处输入图像描述

更新2

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

在此处输入图像描述

Chakra是微软的图书馆。

在此处输入图像描述 在此处输入图像描述

所以现在我有2个问题。

  1. 是ChakraCore有泄漏还是正在使用/分配它? 如何定义哪个库?

2-它说27,000个分配。 这是否意味着内存中仍有27,000个或者其中一些可能被分配然后处理?

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

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

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

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

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

让我们一步一步来做

  1. 使用DebugDiag(捕获连续的挂起转储)
    • 启动DebugDiag Collection并转到Processes选项卡 debugdiag进程选项卡
    • 开始压力测试
    • 检查内存使用情况,一旦达到1 GB,捕获挂起转储
      • 右键单击w3wp.exe进程
      • 选择Create Full Memory dump选项 捕获完整内存挂转
    • 捕获另一个2 GB的转储和一个3.5 GB的转储
    • 您应该在文件夹C:\ ProgramFiles \ DebugDiag \ Logs \ Misc \中捕获转储
    • 右键单击转储文件,然后选择Analyze .NET Memory Issue选项 分析.net内存问题

现在比较每个转储文件(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. Finalizer队列中的热门对象 – 如果您的终结器可能被阻止,这将为您提供任何线索。 对象。 此处和此处讨论类似的问题
  5. 大对象堆上的对象 – 这会导致内存碎片和大对象堆容器对象的大小超过85K。
  6. 缓存,数据表,应用程序域,动态程序集等的大小 。 在一个进程中拥有大量应用程序域并不是一个好主意

请注意,有时debugdiag自动分析无法找出根本原因,需要使用windbg手动分析。 DebugDiag分析,请参考此video 。

希望这可以帮助!

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

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

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

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

  1. 找到内存泄漏的位置。
  2. 修复内存泄漏。

通常第一步很棘手。 所以,我建议继续使用ANTS内存分析器,首先找到正在增长的确切实例

在IIS上分析ASP.NET应用程序

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

在此处输入图像描述

然后按照以下步骤操作。

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

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

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