はじめに
GroupByはシーケンシャルアクセス、Lookupはインデクサアクセスらしいです。
大量データのときどちらが早いのか気になったので計測してみました。
結果
Big Lookup:00:00:15.9899402
Big GroupBy:00:00:18.6203130
Lookupのほうが少し早かったけど劇的ではありませんでした。
大量のオブジェクトコレクションにアクセスする際はやっぱりあらかじめ絞り込まれたコレクションのキャッシュにアクセスすることが大切だということを再認識しました。(大量のマスタへのアクセスとか)
計測
あらかじめこういう計測用のDelegateを用意しておく
readonly Action<string, Action> _measurement = ((desc, execute) =>
{
var sw = new Stopwatch();
sw.Start();
execute();
sw.Stop();
Console.WriteLine("{0}:{1}", desc, sw.Elapsed);
});
1千万件のランダムな文字列をKeyValueコレクションにしてアクセスしてみる時間を計測
var rand = new Random();
var big = new List<string>();
Enumerable.Range(1, 10000000).ForEach(x =>
{
big.Add(rand.Next().ToString());
});
_measurement("Big Lookup", () =>
{
var lookup = big.ToLookup(x => x);
var item = lookup.Where(x => x.Key == "5000000").ToArray();
});
_measurement("Big GroupBy", () =>
{
var group = big.GroupBy(x => x);
var item = group.Where(x => x.Key == "5000000").ToArray();
});
余談
Linqの変換のメソッドでLinqはAs~すると遅延実行される、To~はされないという慣例があるみたいです。拡張メソッドなんかを作る際に考慮されているとありがたいです。