ASP.NET中的FileMonitorTarget / CacheDependency + DepFileInfo导致内存泄漏

时间:2010-07-27 17:35:07

标签: asp.net memory-leaks windbg

在我们的ASP.NET网络应用程序中,我们正在经历一个相当广泛的内存泄漏,我正在调查。使用WinDbg我得到了我们应用程序中最大的内存消费者(在WinDbg控制台中运行!dumpheap -stat来获取这些):

MethodTable Addr   Count  Overall size Type
...
000007fee8306e10   212928     25551360 System.Web.UI.LiteralControl
000007feebf44748   705231     96776168 System.Object[]
000007fee838fd18  4394539    140625248 System.Web.Caching.CacheDependency+DepFileInfo
000007fee838e678  4394614    210941472 System.Web.FileMonitorTarget
000007feebf567b0    18259    267524784 System.Collections.Hashtable+bucket[]
00000000024897c0     1863    315249528      Free
000007feebf56cd0    14315    735545880 System.Byte[]
000007feebf4ec90  1293939   1532855608 System.String

据我所知,大量String个物体可能很正常;仍有绝对的改进空间。但真正让我感到惊讶的是System.Web.FileMonitorTarget个对象的数量:我们在堆上有超过400万个实例(48个字节)!使用两个内存转储并比较它们我发现这些对象没有被GC清理。

我想知道的是:这些物品来自哪里?我已经尝试过ANTS Memory Profiler来找到邪恶的根源,但它无法靠近我们自己的任何类。我看到与System.Web.Caching.CacheDependency+DepFileInfo的连接,因此System.Web.Cache我们不使用文件依赖关系来使我们的缓存条目无效

此外,还有14315个System.Byte[]实例在堆上占用超过700 MB,让我感到震惊 - 我们使用Byte[]的唯一地方是我们的图片上传组件,但我们只有大约30个每天上传图片。

这些Byte数组和FileMonitorTarget对象的来源可能是什么?任何提示都非常受欢迎!

奥利弗

P.S。有人问了同样的问题here,但唯一的'答案'是非常笼统的。

2 个答案:

答案 0 :(得分:1)

我会研究一些事情。你是对的,字符串经常使用很多。你还有约。堆上有1.4 GB的字符串。听起来不错吗?如果不是,我会调查。如果那是预期的范围,请忽略它。

如果您怀疑FileMonitorTarget和/或Byte[]泄露,请使用!dumpheap -mt XXX转储实例,其中XXX是列出的MethodTable类型。您可能希望使用PSSCOR2而不是SOS,因为它使此任务更容易一些(!dumpheap的输出显示增量列,您可以限制转储的实例数。)

接下来要做的是开始研究保持特定实例存活的内容。 !gcroot命令将告诉您特定实例的根。随机选择一个实例并检查根。如果一切都按预期进行到下一个。如果您的应用程序泄漏了这些类型的实例,那么您可能会得到一个应该被释放的实例。一旦获得了根,您需要弄清楚代码的哪一部分正在坚持这些。常见的来源是未订阅的事件,但还有其他可能的原因可以保持对象保持活动状态。

答案 1 :(得分:1)

ASP.NET自动创建System.Web.Caching.CacheDependency + DepFileInfo类型的对象,以监视对您网站的文件更改。因此,即使您没有专门使用FileDependency缓存过期,ASP.NET本身也会这样做。

如果我针对其中一些对象运行转储字段,我会获得控件/页面的路径。

0:000> !df -field _filename 0d3f24ec 
Name: System.String
MethodTable: 79330b24
EEClass: 790ed65c
Size: 180(0xb4) bytes
GC Generation: 2
 (C:\WINDOWS\assembly\GAC_32\mscorlib\2.0.0.0__b77a5c561934e089\mscorlib.dll)
String: C:\inetpub\wwwroot\Website\Application\Base\UserControl\Messages.ascx
Fields:
      MT    Field   Offset                 Type VT     Attr    Value Name
79332d70  4000096        4         System.Int32  1 instance       82 m_arrayLength
79332d70  4000097        8         System.Int32  1 instance       81 m_stringLength
79331804  4000098        c          System.Char  1 instance       44 m_firstChar
79330b24  4000099       10        System.String  0   shared   static Empty
    >> Domain:Value  000e0ba0:02581198 00109f28:02581198 <<
79331754  400009a       14        System.Char[]  0   shared   static WhitespaceChars
    >> Domain:Value  000e0ba0:025816f0 00109f28:02586410 <<

您可以看到此链接描述更多细节:Understanding ASP.NET Dynamic Compilation

但是,您的情况可能仍然不同。尝试运行!GCRoot [obj_addr]并查看保留这些对象的内容。在我的例子中,它完全是IIS / .NET相关的对​​象。

那就是说,我仍然遇到了创建数百万个缓存对象的问题,我不明白为什么。 :| (这是第一次发生在我身上,但我认为它不会出现或者会神奇地消失......)