如何检测内存泄漏的位置?

我有一个大型网站,似乎正在吸收正在分配的所有内存。 此站点旁边的服务器上没有其他任何内容。 在一个星期内,它吃掉了2场演出,需要重新启动。 目前这是使用IIS 7的服务器2008 32位。我们重新安装使用64位并添加更多内存。 能够追踪泄漏发生的位置会很好。

那么跟踪内存泄漏的最佳做法是什么?

在您的代码上运行探查器。

这里有两个不错的选择:

RedGate的内存分析器

Jetbrains dotTrace

我相信这两款产品都有免费试用版。

.NET中的内存泄漏并不常见,但是当它们发生时,最常见的原因是未连接的事件处理程序。 确保在侦听器超出范围之前分离处理程序。

另一种选择是忘记在IDisposable资源上调用Dispose() 。 这可能会阻止清理非托管资源(不由GC处理)。

而另一个可能的原因是一个僵局的终结者。 这将阻止收集终结器队列中的所有剩余对象。

我使用WinDbg + Sos来追踪泄漏。 步骤如下

  • 转储堆并寻找嫌疑人
  • 使用!gcroot找出让嫌犯活着的原因
  • 根据需要重复

请注意,大量内存使用也可能是由于堆碎片造成的。 常规堆被压缩,但固定的对象可能导致碎片。 此外,LOH没有压实,因此LOH的碎片并不少见。

关于WinDbg + sos的优秀教程: http : //blogs.msdn.com/tess/

运行,不要走,转到Tess Ferrandez的博客, 如果它被破坏了,你应该修复它 ,它有很好的脚本实验室致力于学习如何诊断和调试.NET代码的崩溃,挂起和内存问题。 她有一些迄今为止我发现的最好的材料,可以帮助你入门。

诸如ANTS和SciTech之类的商业内存分析器是极好的资源,它们将显示堆中的对象以及它们的根源。 大多数商业内存分析器都能够加载进程的内存“快照”(例如,从您的生产环境中)。

您可以使用adplus.vbs或DebugDiag捕获内存“snap”(请参阅Snap v.Dump)。 Adplus作为Windows调试工具的一部分提供。 DebugDiag还将自动进行一些初步分析(但在非托管代码上似乎更可靠)。

监控应用程序
有关要监视的内容的概念,请参阅提高.NET性能和可伸缩性 ,特别是第15章。

至于如何监控,也有可用的商业工具,但是,每台Windows机器还附带Perfmon.exe,可用于记录相关的性能计数器。

测试应用程序
有关如何执行负载或压力测试的想法,请查看Web应用程序的模式和实践性能测试指南 。

调试应用程序
一旦你发现你遇到问题(监控)并且能够重现问题(测试),你就可以开始调试问题了。 查看苔丝的链接 – 这些信息将为您带来很长的路要走。

然后冲洗并重复! 🙂

祝好运!
ž

在性能监视器中,为所有堆中的进程/专用字节和.NET CLR内存/#字节添加计数器。 专用字节是所有内存,只管理CLR内存。 因此,如果CLR内存保持相当均匀,但私有字节会随着时间的推移而持续增长,这意味着泄漏位于非托管资源中。 这通常意味着您没有正确处理本机资源。 好看的是COM或IO(流和文件)之类的东西。 完成后,确保所有这些东西都被处理掉了。

您可以尝试使用dotTrace等分析器 – 将其设置为内存跟踪并运行您的应用程序。

这应该可以为您提供线索,其中应用程序的程序集和区域会占用大量内存。

这可能是预防而不是检测,但在c#代码级别,您应该检查使用大型资源(如图像和其他文件)的任何类是否正确实现了dispose模式 。 如果需要,您可能还需要覆盖终结器。

MSDN对此主题有很好的指导。

如果您的应用程序中有任何您知道使用大量资源的类,那么这些是第一个查找内存问题的地方。

我发现EQATEC Profiler相当不错,而且它是免费的!

查看此博客文章中的内存和内存泄漏实验:

.NET调试演示

他们可能会有所帮助。 基本上,您可以使用WinDBG分析内存转储并帮助确定占用所有内存的内容。

我们使用类似的方法来确定Regex正在咀嚼我们所有的内存,但只有当产品在64位计算机上运行时才会这样。 学习曲线有点陡峭,但WinDBG是一个非常强大的工具。

我的这篇新文章可能很有用: 如何检测和避免.NET应用程序中的内存和资源泄漏

你做任何Office互操作吗? 如果是这样,请确保清理应用程序对象。 这是一个可能的罪魁祸首。

另一个是全局对象,例如任何静态的对象。

您的网站上有很多动态页面吗?

您也可以尝试IBM的Purify

我建议您尝试使用一小组动态页面,同时禁用所有其他页面。 我讨厌这样说,但IIS 7很可能也有漏洞。

请查看有关检测.NET应用程序内存泄漏的文章以及页面底部提到的相关文章,希望您能找到解决方案或至少有一个想法来解决它。

谢谢