5

目前我正在优化一个巨大的批处理程序的内存使用。不同的数据表使用最多的内存。例如,我的 DataTabledataTable使用了大约 260MB。

就像线程接受的答案中的建议一样“在 .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 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!)

我正在使用 Clear、Dispose 并将其设置为 null,因为在以下线程中建议使用它:Datatable.Dispose() 将使其从内存中删除?

查看停止点注释以查看该点的内存使用情况。我也试过了,using (DataTable dataTable = ...)但结果是一样的。

我究竟做错了什么?也许有更好的方法来缩小 DataTable 中的数据?

4

1 回答 1

5

我终于找到了这个关于内存使用的线程:.NET EXE 内存占用

接受的答案如下:

TaskManager 不应用于测量 .NET 应用程序的内存占用。

当 .NET 应用程序启动时,它会向操作系统请求一块内存,然后将其分段为托管堆、堆栈和大型对象堆。TaskManager 报告的正是这个总内存块,它可能会或可能不会被 .NET 完全使用。一旦为 .NET 应用程序提供了一块内存,它将在操作系统要求之前不会释放它,这只会在操作系统确定需要更多内存资源时发生。

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

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

可以使用 GarbageCollector 通过以下代码获取真正使用的内存:

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

我用我的代码尝试了这个,删除数据表将使用的总内存减少了 28MB。将数据从 DataTable 提取到另一个容器并不值得付出努力:-/

我希望这可以帮助其他有同样问题的人。

有关 GC、Dispose 和 Finalize 的更多信息,您绝对应该查看这个答案

于 2014-11-05T12:36:13.020 回答