首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ASP.NET网站内存使用率很高

ASP.NET网站内存使用率很高
EN

Stack Overflow用户
提问于 2010-08-04 20:41:48
回答 7查看 20.1K关注 0票数 20

我有一个ASP.NET网站,它将在大约3-4天内占用大约2 2gb的物理内存,对我来说这听起来真的很糟糕。目前,我已经将IIS配置为在达到500mb时重新启动应用程序池进程。我想试着追查这个问题。

在.NET中创建对象的新实例时,我的印象是不需要释放它,因为.NET垃圾收集器将为我做这件事。

这是真的吗,或者这可能是我遇到问题的原因之一?

EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2010-08-04 20:55:17

.NET将非常高效地为您管理垃圾收集。虽然在实现IDisposable的类型上调用Dispose方法是明智的,但这可能不是您的问题。在.NET中发生内存泄漏的原因有很多。下面是一些例子:

  • 您在会话中为每个用户缓存了太多数据。
  • 您在应用程序缓存中或在会话或应用程序级别中的静态变量(如dictionary.
  • You
  • web控件)中缓存了太多数据。
  • 您将实例关联到静态类型上的事件或持续被引用的类型(因为它们存储在缓存中)。

我希望这能给你一些关于在哪里寻找的想法。

更新:关于ASP.NET调试,你应该关注this video

更新2:关于你对我的回答的评论如下。CLR将收集所有托管内存,因此将收集您使用new创建所有对象。从这个意义上说,对象是否实现IDisposable并不重要。但是,在很多情况下,您需要直接或间接地使用本机资源(如文件句柄、图形句柄、数据库连接、本机-thus非托管内存的使用)。CLR不知道如何释放这些资源。为此,.NET有终结器的概念。终结器是类的开发人员可以实现的虚拟方法。执行此操作时,CLR将在该类型的实例未被引用且未被回收之前调用此方法。终结器通常包含释放这些资源的逻辑。换句话说,当一个类型需要本机资源时,它通常会有一个终结器方法,允许该类型释放这些资源。

关于CLR,故事到此结束。CLR对实现IDisposable接口的对象没有特定的处理。然而,.NET垃圾收集器本质上是不确定的。这意味着您不知道它何时运行以及是否运行。这意味着在清理本机资源之前可能需要很长时间(因为终结器只会在collect之后被调用)。然而,对于许多资源来说,一旦你使用完它们,就有必要发布它们。例如,当您不关闭数据库连接时,或者当您通过System.Drawing名称空间在.NET中使用GDI+时,数据库连接很快就会耗尽。

出于这个原因,引入了IDisposable接口。同样,CLR和垃圾回收器不会查看此接口。它是类型和它的用户之间的契约,允许它的用户直接释放对象的底层资源。在正常的设计中,对象的终结器和对象的Dispose方法都将调用相同的私有或受保护的方法来释放这些资源。当一个类型实现IDisposable时,明智的做法是在完成时调用它的Dispose方法,或者将对象包装在using语句中,以使本机资源的释放具有确定性。

所以回到你的问题上来。所有托管对象都将由GC收集,但本机资源不会。因此类型可能会实现终结器方法,而这些对象通常也会实现IDisposable接口。对它们调用Dispose将显式地直接释放这些本机资源。

我希望这是有意义的。

票数 18
EN

Stack Overflow用户

发布于 2010-08-04 20:51:54

内存使用率高的原因可能有很多,但.NET中的垃圾回收是一个非常精确的东西。也就是说,它为您做了很多事情,但有时并不像您预期的那样多。

具体地说,它只能清理没有活动引用的对象,所以如果您已经处理完一个类,但仍然有一个对它的引用,那么您将需要删除该引用,以便GC可以为您恢复该内存。此外,如果您有任何非活动的打开连接(例如,到数据库或其他东西),不要忘记关闭并清除它们。通常,我们将这样的对象包装在using块中,如下所示:

代码语言:javascript
复制
using(SqlConnection conn = new SqlConnection(myConnString))
{ ...rest of code here }

这将自动关闭并释放连接。这是作为try...finally块实现的,因此即使在using块中抛出异常,连接也会关闭。

除此之外,答案是"profile,profile,profile“,直到你找到你的漏洞/瓶颈/任何东西。

票数 6
EN

Stack Overflow用户

发布于 2010-08-04 20:56:46

有几件事你应该看一看:

首先,你在使用会话吗?它们是在proc会话中还是在SQL会话中?如果它们正在处理中,那么超时设置为多少?如果你有一个非常长的超时,这可以解释为什么你使用这么多的内存(用户会话将存储很长时间)。

第二,对象的处理。.NET垃圾回收器将为您清除引用,但是当您创建实现IDisposable接口的对象时,应该始终使用using关键字。

代码语言:javascript
复制
using(Foo foo = new Foo())
{
    ...
}

等同于做:

代码语言:javascript
复制
Foo foo;
try
{
    foo = new Foo();
    ...
}
finally
{
    foo.Dispose();
}

它将确保你有效地处理你的对象。

如果您仍然无法在代码中找到任何明显的东西,您可以分析它,从调用次数最多的方法开始。你可以找到关于好的分析器here的信息。这肯定会让你找到问题的根源。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/3405557

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档