1. 程式人生 > 其它 >向DataRow動態新增很多Column時佔用記憶體大且無法釋放[解決]

向DataRow動態新增很多Column時佔用記憶體大且無法釋放[解決]

技術標籤:學習筆記動態複製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);