はじめに
DataTableへのアクセスは、比較的遅いという結果が出ています。
そして、Listの場合だと約5倍以上の速度が出るとも言われています。
DataTableに対するアクセス速度を比較する記事はいくつかありましたが、DataTableをList
今回の比較対象は下記の通りです。
- DataTableを素直にループしてListに格納する
- Linqを利用してListに変換する
- リフレクションを利用してListに変換する
上記3つの変換方法に対して測定を実施してみます。
測定環境
- Visual Studio 2019 Professional
測定時のデータ
- カラム数:4カラム
- レコード数:100万
ソース
今回は5回ループさせた結果を取得します。
(SamplePropertyクラス)
class SampleProperty
{
public string Sample1 { get; set; }
public string Sample2 { get; set; }
public string Sample3 { get; set; }
public string Sample4 { get; set; }
}
(Mainクラス)
static void Main(string[] args)
{
int dataCount = 1000000;
// DataTableを作成する
var dt = new DataTable();
dt.Columns.Add("Sample1");
dt.Columns.Add("Sample2");
dt.Columns.Add("Sample3");
dt.Columns.Add("Sample4");
for (var j = 0; j < dataCount; j++)
{
var dr = dt.NewRow();
for (var i = 0; i < dt.Columns.Count; i++)
{
dr[dt.Columns[i].ColumnName] = Guid.NewGuid().ToString("N");
}
dt.Rows.Add(dr);
}
List spList = new List();
var stopwatch = new Stopwatch();
//ループを使った処理
for(int loop = 0; loop < 5; loop++)
{
stopwatch.Start();
for (int result = 0; result < dt.Rows.Count; result++)
{
SampleProperty sp = new SampleProperty();
sp.Sample1 = dt.Rows[result]["Sample1"].ToString();
sp.Sample2 = dt.Rows[result]["Sample2"].ToString();
sp.Sample3 = dt.Rows[result]["Sample3"].ToString();
sp.Sample4 = dt.Rows[result]["Sample4"].ToString();
spList.Add(sp);
}
stopwatch.Stop();
Console.WriteLine("計測時間(Loop): " + stopwatch.ElapsedMilliseconds + "ms");
stopwatch.Reset();
spList = new List();
// Linqを使った処理
stopwatch.Start();
spList = (from DataRow dr in dt.Rows
select new SampleProperty()
{
Sample1 = dr["Sample1"].ToString(),
Sample2 = dr["Sample2"].ToString(),
Sample3 = dr["Sample3"].ToString(),
Sample4 = dr["Sample4"].ToString()
}).ToList();
stopwatch.Stop();
Console.WriteLine("計測時間(Linq): " + stopwatch.ElapsedMilliseconds + "ms");
stopwatch.Reset();
spList = new List();
// Generic Methodを使った処理(Refrection)
stopwatch.Start();
spList = ConvertDataTable(dt);
stopwatch.Stop();
Console.WriteLine("計測時間(Refrection): " + stopwatch.ElapsedMilliseconds + "ms");
stopwatch.Reset();
spList = new List();
}
}
private static List ConvertDataTable(DataTable dt)
{
List data = new List();
foreach (DataRow row in dt.Rows)
{
T item = GetItem(row);
data.Add(item);
}
return data;
}
private static T GetItem(DataRow dr)
{
Type temp = typeof(T);
T obj = Activator.CreateInstance();
foreach (DataColumn column in dr.Table.Columns)
{
foreach (PropertyInfo pro in temp.GetProperties())
{
if (pro.Name == column.ColumnName)
pro.SetValue(obj, dr[column.ColumnName], null);
else
continue;
}
}
return obj;
}
結果
それぞれの測定結果は下記の通りとなりました。
対象 | Loop | Linq | Refrection |
---|---|---|---|
1回目 | 1020ms | 417ms | 2127ms |
2回目 | 973ms | 407ms | 2340ms |
3回目 | 983ms | 407ms | 2061ms |
4回目 | 988ms | 400ms | 2078ms |
5回目 | 986ms | 413ms | 2084ms |
上記をみてみると、Linqでの変換が一番早く、Refrectionを利用した場合はLinqを使用した場合の時と比べて5倍も時間がかかっているという結果が得られました。
変換方法によってはかなり差がでています。
最後に
少ないデータの場合だとどの変換方法を利用しても問題はありませんが、大規模データの場合は、かなりの差がでます。
参考になれば幸いです。