Memory leaks w3wp.exe垃圾堆充满了可用的对象空间,并且不断增长

Memory leaks w3wp.exe垃圾堆充满了可用的对象空间,并且不断增长,memory-leaks,garbage-collection,heap,w3wp.exe,Memory Leaks,Garbage Collection,Heap,W3wp.exe,我的IIS应用程序(.NET 4.0,IIS7)在内存中不断增长,并最终崩溃,就像我有内存泄漏一样 所以我拿了一个DMP,当它的容量大约为1.7GB时,我在WinDbg中打开了它 dumpheap-stat命令显示,虽然堆中有相当数量的对象,但大多数对象(以及在查看顺序DMP时正在增长的位)被标记为“空闲”(>800MB): 000007feef55b768 46091 2212368系统.数据.数据行视图 000007fe9739dda8 10355 2236680 Newtonsoft.Js

我的IIS应用程序(.NET 4.0,IIS7)在内存中不断增长,并最终崩溃,就像我有内存泄漏一样

所以我拿了一个DMP,当它的容量大约为1.7GB时,我在WinDbg中打开了它

dumpheap-stat命令显示,虽然堆中有相当数量的对象,但大多数对象(以及在查看顺序DMP时正在增长的位)被标记为“空闲”(>800MB):

000007feef55b768 46091 2212368系统.数据.数据行视图
000007fe9739dda8 10355 2236680 Newtonsoft.Json.Serialization.JsonProperty
000007fef4260610 33062 2644960系统。签名
000007fef4242250 41809 4682608系统.反射.运行时方法信息
000007fef424f058 69232 8847997系统。字节[]
00000 7FEF424B28 11 9437680系统。双[]
000007fef4237ca0 15 9505176系统。日期时间[]
000007fef424c168 32559 11009308系统。字符[]
000007fef424dc30 17271 11795376系统。Int32[]
000007 feef55c48 908 17936672 System.Data.RBTree`1+节点[[System.Int32,mscorlib]]][
000007feef554f58 853 22056952 System.Data.RBTree`1+节点[[System.Data.DataRow,System.Data]]][
000007feef5514b0 541444 51978624系统数据数据行
000007fef424aee0 1550958 132599872系统。字符串
000007FEF42F1B8 183607 178409288系统。对象[]
0000000000 D8B2D0 234017 844500226免费

然后我运行了“!dumpheap-type Free”,它给了我很多小的空闲对象(精确地说,每个都是94字节!),最后是几个更大的“空闲”对象:

0000000 3098A59B00000000000 D8B2D0 134免费
0000000 3098C19D00000000000 D8B2D0 102免费
0000000 3098FFA0000000000 D8B2D0 54免费
0000000 309A41D98 0000000000 D8B2D0 5961750免费
0000000 41F8A1000 0000000000 D8B2D0 24免费
0000000 42001B4D0 0000000000 D8B2D0 16933078免费
0000000 4211BF7C8 0000000000 D8B2D0 7702免费
0000000 4212C1600 0000000000 D8B2D0 35173374免费
0000000 4236B3BE0 0000000000 D8B2D0 66886免费
0000000 423CC41E8 0000000000 D8B2D0 10778318免费
0000000 424768928 0000000000 D8B2D0 2254734免费
0000000 4249EC128 0000000000 D8B2D0 21166350免费
0000000 42600F1E00000000000 D8B2D0 51366免费
0000000 42621BAC8 0000000000 D8B2D0 114007238免费

注意到“d8b2d0”的重复地址,我运行了一个“!gcroot d8b2d0” 对此,我得到了以下结果:

0:000>!gcroot d8b2d0
找到0个唯一根(运行“!GCRoot-all”查看所有根)

所以。。。毕竟。。。我的堆上有大量的空闲对象,GC不会释放它们。这大约需要2-3个小时。没有其他迹象表明实际类型化对象存在内存泄漏。它几乎发生在我们生产的所有虚拟机上

有人知道如何处理GC在堆上留下如此多的可用对象空间吗


这让我好几天都在兜圈子。那么,为能帮我解决这个问题的天才干杯

如果您确定您的应用程序存在内存泄漏,我建议您使用memory profiler启动本地分析。这可能比在生产中分析内存转储更快地揭示问题的根源。

多亏了关于使用PerfView的建议,并且在多次非常大的内存转储之后,我找到了这个问题的根源,原因是在Linq表达式中使用了DataRow.DefaultIfEmpty()。它是支持函数的一部分,用于在两个数据表之间执行LeftJoin

使用DataRow枚举中的DefaultIfEmpty()作为Linq表达式的一部分,我可以在几分钟内重新创建一个4GB+的内存空间。通过创建大量的ItemArrayObject(无论是小对象堆还是大对象堆),大部分都可以保存到Gen2 GC集合中。这反过来又会导致承诺内存值不断攀升。GC2集合无法跟上小堆的速度,而大堆的重用性很差(如果有的话)

我们已经调用了这个函数,同样的消遣在提交内存中永远不会超过50MB。现在我们需要看看这对我们的DataTable连接有什么影响,但是内存堆的神秘问题已经解决了


谢谢大家的帮助。

这是Asp.Net应用程序吗?是否使用了特定的框架或库?是的,它是asp.net。主要是数据表和一些使用net.pipe的本地WCF。您是否有任何互操作代码或直接分配
GCHandle
s的代码?我在想,也许你有很多固定的对象,它们阻止了压缩。我认为这可能是问题所在,但我决定要确切地发现其来源是什么。。。Datatables(或者更具体地说,使用then的某种方式)或WCF或其他东西!?使用PerfView并选择“从转储获取堆快照”。现在在PerfView中打开生成的gcdump文件,查看更好的概述:感谢您的建议。我已经经历了这一切。没有内存泄漏,这让我转而研究内存DMP文件。从上面的分析来看,it公司(我相信)确实没有内存泄漏。否则,这个800MB+的大数据块将有一个gcroot或至少是某种类型的对象类型。相反,它实际上被标记为免费的,但是GC不会发布它!?你能陈述一下你为得出这个结论所采取的步骤吗?我正在努力寻找一个非常相似的情况的原因。从下载并学习如何为托管代码获取内存转储文件开始。有一个更广泛的设置,用于在崩溃发生或超过性能限制时触发它们,但我只是在我的应用程序启动时(然后在它膨胀时)将调试器连接到它,并创建快照内存转储。然后,我将内存转储加载到PerfView(如上所述),这样就可以轻松地浏览对象。比较第一个sna
Statistics:
              MT    Count    TotalSize Class Name
000007fef31e7460        1           32 System.Net.SafeLocalFree
0000000000d8b2d0   234017    844500226      Free
Total 234018 objects