我有一个 ASP.NET 网站,它将在大约 3-4 天内使用大约 2gb 的物理内存,这对我来说听起来很糟糕。目前,我已将 IIS 配置为在达到 500mb 时重新启动应用程序池进程。我想尝试找出问题所在。
在 .NET 中创建对象的新实例时,我的印象是不需要释放它,因为 .NET 垃圾收集器会为我执行此操作。
是这种情况还是这可能是我遇到问题的原因之一?
最佳答案
.NET 将非常有效地为您管理垃圾收集。在实现 IDisposable
的类型上明智的做法是调用Dispose
方法,这可能不是你的问题。 .NET 中可能发生内存泄漏的原因有很多。这里有几个:
我希望这能给你一些关于在哪里看的想法。
更新:你应该看 this video关于 ASP.NET 调试。
更新 2:
关于您对我的回答的评论如下。
CLR 将收集所有托管内存,因此您使用
new
创建的所有对象将被收集。从这个意义上说,对象是否实现 IDisposable
并不重要。或不。然而,很多时候您需要直接或间接使用 native 资源(例如文件句柄、图形句柄、数据库连接、使用 native - 因此是非托管内存)。 CLR 不知道如何释放这些资源。为此,.NET 具有终结器的概念。终结器是类的开发人员可以实现的虚拟方法。执行此操作时,CLR 将在该类型的实例未被引用且被收集之前调用此方法。终结器通常包含释放这些资源的逻辑。换句话说,当一个类型需要本地资源时,它通常会有一个终结器方法允许该类型释放这些资源。至于 CLR 呢,故事到此结束。 CLR 没有对实现
IDisposable
的对象的特定处理。界面。然而,.NET 垃圾收集器本质上是不确定的。这意味着您不知道它何时运行以及是否运行。这意味着在您的原生资源被清理之前可能需要很长时间(因为终结器只会在收集后被调用)。然而,对于许多资源,有必要在使用完它们后立即释放它们。例如,当您不关闭数据库连接或通过 System.Drawing 命名空间在 .NET 中使用 GDI+ 时,您往往会很快用完数据库连接)。出于这个原因,
IDisposable
介绍了界面。同样,CLR 和垃圾收集器不会查看此接口(interface)。它是类型与其用户之间的契约,允许其用户直接释放对象的底层资源。在正常设计中,对象的终结器和对象的 Dispose
方法将调用相同的私有(private)或 protected 方法来释放这些资源。当一个类型实现 IDisposable
将其称为 Dispose
是明智的。完成后的方法或将对象包装在 using
中声明允许本地资源的释放是确定性的。所以回到你的问题。 GC 将收集所有托管对象,但 native 资源不会。因此,类型可能会实现终结器方法,而这些对象通常也会实现
IDisposable
界面。调用Dispose
在它们上将显式地直接释放那些原生资源。我希望这是有道理的。
关于.net - ASP.NET 网站内存使用率相当高,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3405557/