使用DataTable的ASP.NET内存泄漏/高内存 [英] ASP.NET Memory Leak/High Memory using DataTable

查看:53
本文介绍了使用DataTable的ASP.NET内存泄漏/高内存的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have an asp.net website that is being hosted in IIS. I have recently noticed that with large result sets being returned from the database, that the memory for IIS Worker Process just keeps growing (about 400MB each time the query is run). If a few of these large queries happen to be run at the same time it can just eat away at the memory (have seen it reach 5GB) and the server slows right down.

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

I have narrowed it down to a single line of code, when the data is loaded into the 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超出范围时,或者在导航页面离开或什至当用户注销站点时,内存将保持在同一级别.在多用户系统中,这显然是一个问题.

What I dont understand is that the memory being allocated to the DataTable doesn't seem to be disposed of as I would expect. When the DataTable falls out of scope or when the webpage is navigated away from or even when the user logs out of the site, the memory stays at the same level. This is obviously an issue in a multi user system.

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

I have used a memory profiler and it is holding thousands of strings in memory which are the results of the query held in the DataTable, but I am not really sure where to go from here? Am I misunderstanding how I should be handling this?

推荐答案

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

It's not the issue. It's how Garbage Collector works. When you dispose of an object it is not removed from memory right away. It's just marked as ready to be disposed of for garbage collector.

这是MS考试书的引文

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

The stack is automatically cleared at the end of a method. The CLR takes care of this and you don’t have to worry about it. The heap is another story—it is managed by the garbage collector. In unmanaged environments without a garbage collector, you have to keep track of which objects were allocated on the heap and you need to free them explicitly. In the .NET Framework, this is done by the garbage collector.

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

The garbage collector works with a mark and compact algorithm. The mark phase of a collection checks which items on the heap are still being referenced by a root item. A root can be a static field, a method parameter, a local variable, or a CPU register. If the garbage collector finds a "living" item on the heap, it marks the item. After checking the whole heap, the compact operation starts. The garbage collector then moves all living heap objects close together and frees the memory for all other objects. For doing this, the garbage collector has to make sure that no state is changing while performing all the marking and compacting. Because of this, all threads are frozen while doing a collect operation. It also has to make sure that all references to living objects are correct. After moving objects around, the garbage collector will fix all existing references to objects.

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

You can try to force garbage collector to perform cleaning using:

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

此外,GC使用了多个世代,只有第0世代易于清理,并且GC首先对其进行清理.只有到那时GC才决定无法释放足够的内存,它将开始处理其他世代.迁移到这些世代可能会造成延迟.

Moreover, GC uses multiple generations and only Generation 0 is easy to clean-up and GC clean it up first. Only then GC decided that it cannot release enough memory it will start to process the other generations. And moving to these generations could create latency.

更新:您也可以尝试将大数据集分成小块,然后进行相应的检索.

UPDATE: You can try also divide your big dataset to small chunks and retrieve them accordingly.

这篇关于使用DataTable的ASP.NET内存泄漏/高内存的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆