2014-11-05 225 views
4

目前,我正在優化大型批處理程序的內存使用情況。最多的內存由不同的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

回答

3

我終於找到了這個線程對內存使用:.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中提取到另一個容器: -/

我希望這可以幫助一些其他遇到同樣問題的人。