DataTable よりも List を使うと 10 倍早くなる(続編)

うちのサイトでは地味にアクセス数が多いページで、

意外と遅い DataTable 、なので List を使うと 5 倍早くなる | Moonmile Solutions Blog
http://www.moonmile.net/blog/archives/2228/comment-page-1#comment-24840175301577487

というのがあります。もう4年程前の記事で、業務で VB.NET 2.0 を使わないといけなくて、LINQ が使えなかったので、DataTable にしようか、List にしようかという調査の記録です。今だと、もうちょっと色々なやり方があるのですが、ちょっとコメントとが付いたので、計測しなおしてみました。

■list を使う
■list に構造体を使う

上記2つのケースについて、他の3つのケースにて行っている
「あえて最初に行を追加しておく」処理の記述がないように
お見受けしますが、これは単なる誤記であり実際は記述の上
実行された計測結果ということでしょうか。

随分前だったので覚えていないのですが、おそらく比較コードのミスです。あらかじめ1万行いれておいたのは「更新系」をチェックする必要があったので、このままだと list のほうが有利に働きますよね。
気になったので Go4 と Go5 だけ抜き出して書き直しました。

実験コード

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }
 
    DataTable MakeDataTable()
    {
        var dt = new DataTable();
        for (int i = 0; i < 100; i++)
        {
            dt.Columns.Add(new DataColumn("x" + i.ToString(), typeof(string)));
        }
        return dt;
    }
 
    double Go4()
    {
        var dt = MakeDataTable();//  new DataTable();
        // データ更新チェックのため、あらかじめ1万行を作る
        for (int i = 0; i < 10000; i++)
        {
            var row = dt.NewRow();
            dt.Rows.Add(row);
        }
        // 計測開始
        var start = DateTime.Now;
        var tm = DateTime.Now;
        for (int i = 0; i < dt.Rows.Count; i++)
        {
            var row = dt.Rows[i];
            for (int j = 0; j < 100; j++)
            {
                row[j] = tm.ToShortDateString(); tm.AddSeconds(1);
            }
        }
        var tend = DateTime.Now;
        var span = (tend - start).TotalSeconds;
        return span;
    }
 
    double Go5()
    {
        var dt = new List<object>();
        // データ更新チェックのため、あらかじめ1万行を作る
        for (int i = 0; i < 10000; i++)
        {
            var row = new object[100];
            dt.Add(row);
        }
        // 計測開始
        var start = DateTime.Now;
        var tm = DateTime.Now;
        for (int i = 0; i < dt.Count; i++)
        {
            var row = dt[i] as object[];
            for (int j = 0; j < 100; j++)
            {
                row[j] = tm.ToShortDateString(); tm.AddSeconds(1);
            }
        }
        var tend = DateTime.Now;
        var span = (tend - start).TotalSeconds;
        return span;
    }
 
    /// <summary>
    /// DataTable を利用
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void button1_Click(object sender, EventArgs e)
    {
        var t = this.Go4();
        label1.Text = t.ToString();
    }
 
    /// <summary>
    /// list を利用
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    private void button2_Click(object sender, EventArgs e)
    {
        var t = this.Go5();
        label1.Text = t.ToString();
    }
}

どちらも、1万行いれておいて、その行に対して逐一データを修正するというスタイルになっています。
コードは Visual Studio 2013 を使っています。

実験結果

DataTable 8.32, 8.12, 8.12 sec
list 0.88, 0.83, 0.83 sec

とう具合に、DataTable よりも list のほうが 10 倍早くなっています。
すべてオンメモリで動くために、後は CPU 速度の違いになるとは思うのですが、PC が異なるし(こっちの PC のほうが断然早いので)相対的な結果になります。以前の 4,5倍よりも開きが大きくなっています。絶対値の違いは、VB が C# よりも遅いのではなくて、計測する CPU の差です。

カテゴリー: 開発 パーマリンク