![IIS 应用程序池占用过多内存](https://linux22.com/image/740479/IIS%20%E5%BA%94%E7%94%A8%E7%A8%8B%E5%BA%8F%E6%B1%A0%E5%8D%A0%E7%94%A8%E8%BF%87%E5%A4%9A%E5%86%85%E5%AD%98.png)
我们在两台服务器(IIS8 和 10)上运行 IIS,最近发现我们的 ASP.NET WebForms 应用程序的内存使用率非常高,大多数是通过 aspx 页面访问的。
实际情况是,随着时间的推移,我们的应用程序池消耗的内存越来越多,直到服务器上的物理内存(64GB)几乎耗尽。这绝对是不正常的。
我们试图找出发生这种情况的原因,但没有办法。目前还不清楚这是我们应用程序中的内存泄漏还是正常行为,所以也许有人可以解释一下。
事实:
随着时间的推移,应用程序池保留并使用越来越多的内存,这些内存不会被释放(任务管理器说工作集和提交大小都很高,所以它实际上被使用/持有了,对吗?)
ANTS、.dotMemory、.NET MemoryProfiler 等内存分析器表明,托管内存消耗相当低,比如 20-200MB,并且显示大量非托管内存(将被使用,但却是免费的)。
即使使用快照和详细的分析方法,他们也没有给出可能导致非托管使用的原因的任何提示。
如果我们用 F5 键“敲击”起始页而不释放它,我们可以在一分钟内将内存使用量提高到 2-5 GB。这有点疯狂。
我们知道,IIS/应用程序池倾向于以机会主义的方式保留更多可用内存,但这太多了。
我们唯一看到的是,首页似乎与其控件和 ComponentModel 对象一起保存在内存中,但是在内存分析器的任何地方都没有对我们的任何页面对象或自己的命名空间类的单一引用。
据传,一年前内存消耗情况很好,总共停止在 2-3 GB 左右,但我们无法使用旧版本的应用程序重现这种情况。
在 WIN10 下全新本地安装的 IIS 上也会发生这种情况。
该应用程序是在发布模式下构建的,经过优化,目前已编译为单个 DLL,也尝试过不使用,启用跟踪标志,大小为 5mb
看来我们需要拆开应用程序,将其拆分成几个模块,然后查看它们的行为。运行时加载的程序集/库可能会出现问题,但不应该是问题所在。我们实际上并没有引用那么多(FreeTextBox、Microsoft ReportViewer、SharpCompress、Crystal Reports、AjaxControlToolKit 15),我们已经删除了除 CrystalReports/AjaxControlToolKit 之外的所有程序集,以查看会发生什么,但没有任何变化。
我们还使用许多 WebForms 控件,有时包括 Timers 和 UpdatePanels。
我们也不知道如何使用内存分析器来找到罪魁祸首,假设有一个隐藏的引用导致一个或多个 aspx 页面被保存在内存中,因为 .NET 类实例从未显示任何内容的链接。
我们很乐意得到任何有关我们可能对内存预留的误解或如何解决这个内存消耗问题的提示。
非常感谢您的宝贵时间!
编辑(忘记提及): - 我们将 GC.Collect/WaitForPendingFinalizers/GC.Collect 添加到起始页的 Page_Load 函数中,看看它是否有帮助,结果确实有帮助,直到出现另一种压力情况(使用 F5),内存使用量再次极端上升。
答案1
当 GC.WaitForPendingFinalizers 有帮助时,这可能是线程使用内存的标志。如果您在 page_load 上启动一个新的单独线程,它可能会使用大量内存。通过检查任务管理器中的线程数开始诊断问题。