繁体   English   中英

使用DataTable的ASP.NET内存泄漏/高内存

[英]ASP.NET Memory Leak/High Memory using DataTable

我有一个由IIS托管的asp.net网站。 我最近注意到,随着从数据库返回大量结果集,IIS Worker Process的内存一直在增长(每次运行查询大约400MB)。 如果其中一些大型查询恰巧同时运行,则它可能会消耗掉内存(已经达到5GB),并且服务器会立即变慢。

当数据加载到DataTable中时,我将其范围缩小到一行代码。

using (SqlConnection connection = new SqlConnection(connectionString))
using (SqlCommand command = new SqlCommand(storedProcedureName, connection))
using(DataTable dataTable = new DataTable())
{
    command.CommandType = System.Data.CommandType.StoredProcedure;
    connection.Open();

    using (SqlDataReader reader = command.ExecuteReader())
    {
        // Memory Spikes on dataTable.Load
        dataTable.Load(reader);
    }
}

我不明白的是,分配给DataTable的内存似乎没有像我期望的那样被处置。 当DataTable超出范围时,或者在导航页面离开或什至当用户注销站点时,内存将保持在同一级别。 在多用户系统中,这显然是一个问题。

我使用了一个内存探查器,它在内存中保存了成千上万个字符串,这些字符串是保存在DataTable中的查询结果,但是我真的不确定从哪里走吗? 我是否误解了应该如何处理?

这不是问题。 这就是垃圾收集器的工作方式。 处理对象时,不会立即将其从内存中删除。 它只是标记为准备好用于垃圾收集器处理。

这是MS考试书的引言

方法结束时将自动清除堆栈。 CLR会处理此问题,您不必担心。 堆是另一回事-它由垃圾收集器管理。 在没有垃圾收集器的非托管环境中,您必须跟踪在堆上分配了哪些对象,并且需要显式释放它们。 在.NET Framework中,这是由垃圾收集器完成的。

垃圾收集器使用标记和紧凑算法。 集合的标记阶段检查根项仍在引用堆中的哪些项。 根可以是静态字段,方法参数,局部变量或CPU寄存器。 如果垃圾收集器在堆上找到“活动的”项目,则会对其进行标记。 在检查了整个堆之后,压缩操作开始。 然后,垃圾收集器将所有活动的堆对象移到一起,并为所有其他对象释放内存。 为此,垃圾收集器必须确保在执行所有标记和压缩时没有任何状态发生变化。 因此,所有线程在执行收集操作时都被冻结。 还必须确保所有对活动物体的引用都是正确的。 在移动对象之后,垃圾收集器将修复所有对对象的现有引用。

您可以尝试使用以下方法强制垃圾收集器执行清理:

GC.Collect(); 
GC.WaitForPendingFinalizers(); 

此外,GC使用了多个世代,只有第0世代很容易清理,而GC首先会清理它。 只有到那时GC才决定不能释放足够的内存,它将开始处理其他世代。 而转移到这些世代可能会造成延迟。

更新:您也可以尝试将大数据集分成小块,并相应地进行检索。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM