简体   繁体   English

C#优化内存使用:如何释放DataTable要求的内存

[英]C# optimize memory usage: How to free memory claimed by DataTable

Currently I'm optimizing memory-usage of an huge batch-program. 目前,我正在优化大型批处理程序的内存使用情况。 The most memory is used by different DataTables. 最多的内存由不同的数据表使用。 For examle, my DataTable dataTable is using approx 260MB. 例如,我的DataTable dataTable使用大约260MB。

Like suggestet in the accepted answer of the thread " What is the memory overhead of storing data in a .NET DataTable? " I'm trying to move relevant data out of the DataTable. 就像线程接受的答案中的建议“ 在.NET DataTable中存储数据的内存开销是多少? ”,我正在尝试将相关数据移出DataTable。 This is my code: 这是我的代码:

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 dataRow in dataTable.Rows)
{
    dynamic expandoItem = new ExpandoObject();
    expandoItem.FieldName = dataRow["FieldName"].ToString();
    expandoList.Add(expandoItem);
}
// Second stop point - Total process memory (taskmanager) = 1055 MB
dataTable.Clear();
dataTable.Dispose();
dataTable = null;
GC.Collect(); // force the garbage collector to free memory
// Third stop point - Total process memory (taskmanager) = 1081 MB (wtf? even more!)

I'm using Clear, Dispose and setting to null because it is suggested in following thread: Datatable.Dispose() will make it remove from memory? 我正在使用Clear,Dispose并将其设置为null,因为在以下线程中建议这样做Datatable.Dispose()会将其从内存中删除吗?

See the stop points comments to see memory usage at that points. 请参阅停止点注释以查看该点的内存使用情况。 I also tried it with using (DataTable dataTable = ...) but the results were the same. 我也尝试using (DataTable dataTable = ...)但是结果是相同的。

What am I doing wrong? 我究竟做错了什么? And maybe is there a better way to minify data from DataTable? 也许有更好的方法来减少DataTable中的数据?

I finally found this thread about the memory-usage: .NET EXE memory footprint 我终于找到了有关内存使用的线程: .NET EXE内存占用量

The accepted answer says following: 接受的答案如下:

TaskManager should not be used to measure the memory footprint of a .NET application. TaskManager不应用于衡量.NET应用程序的内存占用。

When a .NET application starts, it asks the OS for a chunk of memory which it then segments to become the managed heap, stack, and large object heap. 当.NET应用程序启动时,它会请求操作系统提供一块内存,然后将其分段以成为托管堆,堆栈和大对象堆。 It is this total chunk of memory that TaskManager is reporting, which may or may not be completely used by .NET. TaskManager报告的就是这块内存,.NET可能会完全使用它,也可能不会完全使用它。 Once a .NET application is given a chunk of memory, it will not release it until asked by the OS, which will only happen with the OS determines a need for more memory resources. 一旦为.NET应用程序分配了一块内存,它就不会释放它,除非得到操作系统的要求,这只有在操作系统确定需要更多的内存资源时才会发生。

If you want to measure memory allocations, you need to look at the various performance > monitor (PerfMon) counters. 如果要测量内存分配,则需要查看各种性能>监视器(PerfMon)计数器。

In short: the task manager shows the reserved memory instead of the really used. 简而言之:任务管理器显示保留的内存而不是实际使用的内存。 This means setting the DataTable to null works fine. 这意味着将DataTable设置为null可以正常工作。

It is possible to use the GarbageCollector to get the really used memory with following code: 可以使用GarbageCollector通过以下代码获取实际使用的内存:

long memoryInMB = GC.GetTotalMemory(forceFullCollection: true) / 1024 / 1024;

I tried this with my code and the removal of the datatable reduced the used total memory by 28MB. 我用我的代码尝试了此操作,删除了数据表,使已使用的总内存减少了28MB。 Not as much to be worth the effort to extract data from DataTable to another container :-/ 从DataTable提取数据到另一个容器的努力并不值得:-/

I hope this can help some other people who have the same problem. 我希望这可以帮助其他有相同问题的人。

For more info's about GC, Dispose and Finalize you should absolutely check out this answer . 有关GC,处置和完成的更多信息,请务必参考此答案

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

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