向DataRow動態新增很多Column時佔用記憶體大且無法釋放[解決]
阿新 • • 發佈:2020-12-15
技術標籤:學習筆記動態複製DataRow動態擴充套件DataRow複製DataRow是佔記憶體複製DataRow記憶體無法釋放快速擴充套件DataRow
現在我們有一個簡單的需求,一個DataRow裡面1萬列(建立它的DataTable有1萬列),我們要把它增加一列併為這個Cell更新一個數據。
DataRow根本沒有新增Column的的方法,我們自然而然會想到複製DataRow的方法。其實也可以一個cell一個cell地複製,但是我們發現可以通過DataRow的ItemArray一次性匯入到新的DataRow。
請參看下面程式碼,我們定義了一個10列的DataTable,然後在新增一行資料時,動態把DataTable擴充套件到10000列,由於我們一開始的DataRow是由原始的10列的Table建立的,所以需要同時動態擴充套件我們的DataRow,這是我們就要用到DataRow的複製。
但是這總方法在當量資料是效率非常低,就下面這個程式碼,足足運行了13秒,佔據記憶體960MB, 而且GC沒有自動回收(不明白為什麼沒有自動回收臨時DataRow變數)。
這個問題其中一個原因:10000列,每新增一個列,都要把前面的所有列複製一遍。
//Total Column count int cnt = 10000; //Define table with 10 columns int fixsize = 10; DataTable dt = new DataTable(); for (int i = 0; i < fixsize; i++) { string colName = "C" + i.ToString(); dt.Columns.Add(colName, typeof(float)); } //Add 1 dataRow and extend to 10000 columns dynamically DataRow dr = dt.NewRow(); for (int i = 0; i < cnt; i++) { string colName = "C" + i.ToString(); add new columns if (i>= fixsize) { dt.Columns.Add(colName); //copy datarow DataRow dr1 = dt.NewRow(); dr1.ItemArray = dr.ItemArray; dr = dr1; } //update data dr[colName] = i * 1.1; } //Add 1 row to table dt.Rows.Add(dr);
這邊我們利用ArrayList實現了高效率的DataRow複製,程式碼如下,這樣在新增Column的過程中沒有複製過程,只是新增到ArrayList, 直到最後再一次性複製到DataRow.
執行時間:0.03秒,記憶體 30MB
//Total Column Count int cnt = 10000; //Define table with 10 columns int fixsize = 10; DataTable dt = new DataTable(); for (int i = 0; i < fixsize; i++) { string colName = "C" + i.ToString(); dt.Columns.Add(colName, typeof(float)); } //Add 1 datarow and extend columns to 10000 DataRow dr = dt.NewRow(); ArrayList al = new ArrayList(dr.ItemArray); for (int i = 0; i < cnt; i++) { string colName = "C" + i.ToString(); //column index < fixsized if (i<fixsize) { al[i] = i * 1.1; } else {//add new columns dt.Columns.Add(colName); al.Add(i * 1.1); } } //define new row with 10000 columns dr = dt.NewRow(); //populate 10000 cells data to dataRow from ArrayList dr.ItemArray = al.ToArray(); dt.Rows.Add(dr);