目前,我正在优化大型批处理程序的内存使用。大多数内存由不同的DataTable使用。例如,我的DataTable dtTest使用大约260MB。
喜欢在线程的接受答案中提出建议" 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!)
我使用Clear,Dispose和设置为null,因为它在以下帖子中建议:Datatable.Dispose() will make it remove from memory?
请参阅停止点注释以查看该点的内存使用情况。我也尝试使用(DataTable dtTest = ...)但结果是一样的。
我做错了什么? 也许有更好的方法来从DataTable中缩小数据?
答案 0 :(得分:3)
我终于找到了关于内存使用的这个帖子:.NET EXE memory footprint
接受的答案如下:
不应使用TaskManager来测量.NET应用程序的内存占用量。
当.NET应用程序启动时,它会向操作系统询问一块内存,然后将其分段 成为托管堆,堆栈和大对象堆。这是总的一大块记忆 TaskManager正在报告,.NET可能会或可能不会完全使用它。曾经是.NET 应用程序被给予一大块内存,直到操作系统询问它才会释放它 只有在OS确定需要更多内存资源时才会发生。
如果要测量内存分配,则需要查看各种性能&gt;监视器(PerfMon)计数器。
简而言之:任务管理器显示保留的内存而不是真正使用的内存。这意味着将DataTable设置为null可以正常工作。
可以使用GarbageCollector通过以下代码获取真正使用的内存:
long lMemoryMB = GC.GetTotalMemory(true/* true = Collect garbage before measuring */) / 1024 / 1024; // memory in megabytes
我用我的代码尝试了这一点,删除数据表将使用的总内存减少了28MB。将数据从DataTable提取到另一个容器的努力并不值得: - /
我希望这可以帮助其他有同样问题的人。