2016年10月27日木曜日

【C#】関数指定とラムダ式の速度差(List.Sort)

◆概要
ラムダ式の方が早いと聞いたので、早速確認してみる。

◆使用データ
①10000, 10001, 10002, …を1000万件
②0, 1, 2, …を1,000万件

上記①②の計2,000万件のデータを一つのリストに入れてSort()メソッドを実行。
Sort()に渡す引数として、以下の(a)(b)を切り替えて、それぞれ速度比較してみる。
 (a)ラムダ式指定
 (b)関数(デリゲート)指定

データはかなりテキトー。入れ替えが発生し、同一データ有を迅速に作りたかっただけ。

◆結論
少しだけラムダ式の方が早い。
ちなみにDebugビルドだとラムダ式が19秒、関数指定が45秒など差が広がる。
今回の趣旨とはずれるが、引数無しSort()の方がもっと早い。IComparerは・・・いずれ試したい。
C++では仮想関数テーブルから選択処理が走って遅いイメージがあるが、C#ではどうなのか?

◆ソースコード1:ラムダ式でソート
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ComparatorVsRambda
{
    class Program
    {
        static void Main(string[] args)
        {
            var list = Enumerable.Range(10 * 1000, 10 * 1000 * 1000).ToList();
            list.AddRange(Enumerable.Range(0, 10 * 1000 * 1000));

            var sw = new Stopwatch();

            sw.Start();
            list.Sort((left, right) => left - right);   // ★★★ここを変更する
            sw.Stop();
            Console.WriteLine(sw.Elapsed);
            Console.ReadKey();
        }

        static int compare(int left, int right)
        {
            return left - right;
        }
    }
}

◆結果1
1回目:15.32秒
2回目:14.32秒

◆ソースコード2:関数指定によるソート
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ComparatorVsRambda
{
    class Program
    {
        static void Main(string[] args)
        {
            var list = Enumerable.Range(10 * 1000, 10 * 1000 * 1000).ToList();
            list.AddRange(Enumerable.Range(0, 10 * 1000 * 1000));

            var sw = new Stopwatch();

            sw.Start();
            list.Sort(compare);   // ★★★ここを変更する
            sw.Stop();
            Console.WriteLine(sw.Elapsed);
            Console.ReadKey();
        }

        static int compare(int left, int right)
        {
            return left - right;
        }
    }
}

◆結果2
1回目:16.99秒
2回目:16.47秒

◆ソースコード3:(参考)引数無しでソート
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ComparatorVsRambda
{
    class Program
    {
        static void Main(string[] args)
        {
            var list = Enumerable.Range(10 * 1000, 10 * 1000 * 1000).ToList();
            list.AddRange(Enumerable.Range(0, 10 * 1000 * 1000));

            var sw = new Stopwatch();

            sw.Start();
            list.Sort();   // ★★★ここを変更する
            sw.Stop();
            Console.WriteLine(sw.Elapsed);
            Console.ReadKey();
        }

        static int compare(int left, int right)
        {
            return left - right;
        }
    }
}

◆結果3
1回目:4.14秒
2回目:4.32秒

◆環境
 ■速度確認した仮想マシン
  • CPU:2
  • メモリ:2GB
  • OS:Windows7
  • 仮想マシン:VMWare WorkStation10
  • Visual Studio 2015 Community
  • 構成:Releaseでビルド
  • デバッグ情報(ビルドの詳細設定):none
  • Visual Studio ホスティングプロセス:無効

 ■ホストPCの性能(参考)
  • CPU:Intel Core i5-4250U
  • メモリ:8GB
  • ドライブ:SSD(Plextor PX-512M3P)
  • OS:Windows10

0 件のコメント:

コメントを投稿