お久しぶりです、エンジニアのMasashiです。
今回はC#を扱う人たちの味方、Linqの疑問について検証を行ってみました。
C#を扱う人たちならば必ず使用するLinqですが、実際データ取得速度はどの程度のものなのでしょうか?
上記について検証を行ってみたいと思います。
測定までの流れ
今回測定を行うのは、Listに格納されているデータから該当のデータを取得する際にかかった時間になります。
データの取得方法については、Linqを使用する方法と使用しない方法での速度比較になります。
測定環境
- Visual Studio 2015
対象データ
- データ数:20,000,000
- Listの中身:0~10,000までの乱数
測定対象
- Loopで判定しながら取得
- Linqを使用
- FindAllメソッドを使用
テストコード
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 |
using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; namespace GetDataSpeedComparison { internal class Program { // データ数 private const int DataCount = 20000000; // 乱数:最大値 private const int MaxNumber = 10000; // 検索する数値 private const int SearchNumber = 2813; private static void Main() { var list = MakeList(); for (var i = 0; i < 10; i++) { Console.WriteLine("----------------"); LoopAccess(list); LinqSelectAccess(list); LinqFindAllAccess(list); Console.WriteLine("----------------"); } Console.WriteLine("続行するには何かキーを押してください:"); Console.ReadKey(); } // Loopで対象データを検索 private static void LoopAccess(List<int> list) { var result = new List<int>(); var stopwatch = new Stopwatch(); stopwatch.Start(); foreach (var number in list) { if (number == SearchNumber) { result.Add(number); } } stopwatch.Stop(); Console.WriteLine("計測時間【Loop】: " + stopwatch.ElapsedMilliseconds + "ms"); } // Whereメソッドを使用して対象データ検索 private static void LinqSelectAccess(List<int> list) { var stopwatch = new Stopwatch(); stopwatch.Start(); var result = list.Where(x=>x == SearchNumber).ToList(); stopwatch.Stop(); Console.WriteLine("計測時間【Select】: " + stopwatch.ElapsedMilliseconds + "ms"); } // Findメソッドを使用して検索 private static void LinqFindAllAccess(List<int> list) { var stopwatch = new Stopwatch(); stopwatch.Start(); var result = list.FindAll(x=>x == SearchNumber).ToList(); stopwatch.Stop(); Console.WriteLine("計測時間【Find】: " + stopwatch.ElapsedMilliseconds + "ms"); } // テストデータ作成(List) private static List<int> MakeList() { var list = new List<int>(DataCount); var r = new Random(); for (var i = 0; i < DataCount; i++) { var row = r.Next(0, MaxNumber); list.Add(row); } return list; } } } |
測定結果
10回試行した結果の平均値が下記になっています。小数点以下は四捨五入しています。
計測項目 | 計測時間(ms) |
---|---|
Loopで判定しながら取得 | 99 |
Linqで取得 | 117 |
FindAllメソッドで取得 | 89 |
上記からListで該当のデータ取得にはFindAllメソッドが一番時間が速い結果になりました。
Linqは処理速度が遅いという記事がよく見られますが、評判通りの結果となりました。
Loopで判定しながら取得する結果は、自分が思っていたよりも短い時間で処理可能であることがわかりました。
今回計測条件を揃えるために、Linq/FindAllメソッドでのデータ取得では、【ToList()】の部分でListに変換後、格納しています。
しかし、Linq/FindAllメソッドの結果をListに変換せず取得すると、取得速度は非常に速くなります。
どれぐらい速いかというとミリ秒では測れない速度結果になります。
Listに変換する処理が非常に時間のかかる処理であることが上記からわかります。
まとめ
特定データの取得速度という面では、今回大きな速度差を見つけることはできませんでした。
実施パターンの中では、Linqが処理速度は一番遅い形になりますが、テストデータの件数から比較すると気になるほどの差ではないと判断できます。
上記処理時間を気にするよりも、Linqを使用した際のメリットである遅延評価とコードの簡潔さからデータ取得方法は、Linqに軍配が上がると思います。
Linqは非常にいろいろな処理が行える便利な機能です。
C#を使ったことがない方もこれを機にC#そして、Linqに触れてみていただければ嬉しいです。