C#优化内存使用情况:如何释放DataTable声明的内存

问题描述:

目前,我正在优化大型批处理程序的内存使用情况。最多的内存由不同的DataTable使用。例如,我的DataTable dtTest使用大约260MB。C#优化内存使用情况:如何释放DataTable声明的内存

像线程“What is the memory overhead of storing data in a .NET DataTable?”接受的答案中的建议我试图将相关数据移出DataTable。这是我的代码:

GC.Collect(); // force the garbage collector to free memory 
// First stop point - Total process memory (taskmanager) = 900 MB 
List<ExpandoObject> ExpandoList = new List<ExpandoObject>(); 
foreach (DataRow drTest in dtTest.Rows) 
{ 
    dynamic ExpandoItem = new ExpandoObject(); 
    ExpandoItem.FieldName = drTest["FieldName"].ToString(); 
    ExpandoList.Add(ExpandoItem); 
} 
// Second stop point - Total process memory (taskmanager) = 1055 MB 
dtTest.Clear(); 
dtTest.Dispose(); 
dtTest = null; 
GC.Collect(); // force the garbage collector to free memory 
// Third stop point - Total process memory (taskmanager) = 1081 MB (wtf? even more!) 

我使用的清除,处置和原因,建议在以下线程设置为null:Datatable.Dispose() will make it remove from memory?

见止动点意见,看看内存使用在那个点。我也尝试过使用(DataTable dtTest = ...),但结果相同。

我在做什么错? 也许有更好的方法来缩小数据从DataTable?

+0

运行一个内存分析器,看看你的数据表(或其他大尺寸的东西)是否仍在被引用。 – fejesjoco 2014-11-05 10:07:10

+0

dtTest从哪里来?它是方法调用的参数吗?如果是这样,它仍然会被调用方法引用,所以它不符合垃圾回收的条件。 – 2014-11-05 15:19:53

+0

它来自相同的功能。问题是我使用任务管理器来检查内存大小。我不知道.NET中有保留的内存。 – Undercover1989 2014-11-06 08:18:51

我终于找到了这个线程对内存使用:.NET EXE memory footprint

接受的答案说以下内容:

任务管理器不应该被用来衡量一个.NET应用程序的内存占用。

当.NET应用程序启动时,它会向操作系统请求一块内存,然后它会将 分段为托管堆,堆栈和大对象堆。这是TaskManager正在报告的这块内存的一大块内存 ,可能也可能不完全由.NET使用。一旦一个.NET应用程序被赋予了一块内存,它将不会释放它,直到被操作系统询问时,它才会与操作系统确定需要更多的内存资源一起发生。

如果要测量内存分配,您需要查看各种性能> monitor(PerfMon)计数器。

总之:任务管理器显示保留的内存而不是真正使用的内存。这意味着将DataTable设置为null可以正常工作。

有可能使用GarbageCollector与下面的代码,以获得真正使用的内存:

long lMemoryMB = GC.GetTotalMemory(true/* true = Collect garbage before measuring */)/1024/1024; // memory in megabytes 

我想这与我的代码,并去除DataTable的由28MB减少所使用的总内存。不值得花费精力将数据从DataTable中提取到另一个容器: -/

我希望这可以帮助一些其他遇到同样问题的人。