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

发布于 2024-09-12 01:05:05 字数 1487 浏览 5 评论 0原文

在我们的 ASP.NET Web 应用程序中,我们遇到了相当大范围的内存泄漏,我现在正在对此进行调查。使用 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< /code> 对象可以是很正常的;仍然肯定有改进的空间。但真正让我感到痒的是 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.有人问了几乎同样的问题这里 但唯一的“答案”非常笼统。

In our ASP.NET web app we're experiencing a quite extensive memory leak which I am investigating right now. Using WinDbg I got down to the largest memory eaters in our app which are (ran !dumpheap -stat in the WinDbg console to get these):

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

For all I know a large number of String objects can be quite normal; still there's definitely room for improvement. But what really makes me itch is the count of System.Web.FileMonitorTarget objects: we have over 4 million instances on the heap (à 48 bytes)! Using two memory dumps and comparing them I've found out that these objects are not being cleaned up by the GC.

What I'm trying to find out is: where are these objects coming from? I've already tried ANTS Memory Profiler to get to the root of the evil but it leads nowhere near any of our own classes. I see the connection with System.Web.Caching.CacheDependency+DepFileInfo and thus the System.Web.Cache but we do not use file dependencies to invalidate our cache entries.

Also, there are 14315 instances of System.Byte[] making up for over 700 MB on the heap which stuns me - the only place where we use Byte[] is our image uploading component but we have only around 30 image uploads per day.

What might be the source of these Byte arrays and FileMonitorTarget objects? Any hints are very welcome!

Oliver

P.S. Someone asked pretty much the same question here but the only 'answer' there was very general.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

三五鸿雁 2024-09-19 01:05:05

我会研究一些事情。你是对的,字符串经常被大量使用。不过你还有大约。堆上有 1.4 GB 的字符串。听起来对吗?如果没有的话我会调查一下。如果在预期范围内,则忽略它。

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

接下来要做的就是开始研究是什么让特定实例保持活动状态。 !gcroot 命令将告诉您特定实例的根。随机选择一个实例并检查根。如果一切都符合预期,则继续下一步。如果您的应用程序泄漏了这些类型的实例,您很可能会得到一个本应被释放的实例。一旦你找到了根源,你就需要弄清楚代码的哪一部分保留了这些。一个常见的来源是取消订阅的事件,但对象保持活动状态还有其他可能的原因。

There are a couple of things I would look into. You're right the strings are often used in great number. Still you have approx. 1.4 GB worth of strings on the heap. Does that sound right? If not I would look into that. If that is withing the expected range, just ignore it.

If you suspect FileMonitorTarget and/or Byte[] to be leaking, dump the instances using !dumpheap -mt XXX where XXX is the listed MethodTable for the types. You may want to use PSSCOR2 instead of SOS, as it makes this task a bit easier (the output from !dumpheap shows a delta column and you can limit the number of instances dumped).

The next thing to do is to start looking into what is keeping specific instances alive. The !gcroot command will tell you what roots a specific instance. Pick an instance at random and inspect the roots. If everything is as expected move on to the next. If you application is leaking instances of these types chances are that you will get an instance that should have been freed. Once you get the roots you need to figure out what part of the code is holding on to these. A common source is unsubscribed events, but there are other possible reasons why objects are kept alive.

烙印 2024-09-19 01:05:05

System.Web.Caching.CacheDependency+DepFileInfo 类型的对象由 ASP.NET 自动创建,以监视网站的文件更改。因此,即使您没有专门使用 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 <<

您可以看到此链接描述了更多详细信息: 了解 ASP.NET 动态编译

但是,您的情况可能仍然不同。尝试运行 !GCRoot [obj_addr] 并查看哪些对象持有这些对象。就我而言,它完全是 IIS /.NET 相关的对象。

也就是说,我仍然遇到一个问题,即创建了数百万个缓存对象,但我不知道为什么。 :| (这是我第一次遇到这种情况,但我不认为它出现或会神奇地消失......)

Objects of type System.Web.Caching.CacheDependency+DepFileInfo are created automatically by ASP.NET to monitor file changes to your website. So even if you are not specifically using a FileDependency cache expiration, ASP.NET itself does.

If I run a dump field against some of these objects, I get a path to my controls/pages.

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 <<

You can see this link describing a bit more detail: Understanding ASP.NET Dynamic Compilation

However, your case might still be different. Try running !GCRoot [obj_addr] and see what is holding onto those objects. In my case it is entirely IIS /.NET related objects.

That said, I still had a problem where millions of these cache objects were created, and I have no idea why. :| (this is the first time it happened to me, but I don't think it appeared or will disappear magically...)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文