LINQの遅延評価がマイナスに働くケース
LINQに限らず遅延評価はパフォーマンスに対してプラスに働く、という説明が多いように思うが、劇的にマイナスに働くケースがあった。 商品の名前の先頭に応じてグループ分けし、残ったデータに対して同様にグループ分けする以下のようなコード
IEnumerable<T> left = .... var sub1 = left.Where(l => l.StartsWith("AB")) left = left.Where(l => sub1.All(s => s.ID != l.ID)) var sub2 = left.Where(l => l.StartsWith("A") left = left.Where(l => sub2.All(s => s.ID != l.ID)) var sub3 = left.Where(l => l.StartsWith("B") left = left.Where(l => sub3.All(s => s.ID != l.ID)) ...
このような分類が20弱続くケースで、1分たっても応答が返ってこない。
leftの型をIListとし、left = left.Where(l => sub1.All(s => s.ID != l.ID)).ToList()
のように即時評価に書き換えると1秒せずに返ってくる。
デバッグ実行すると、left = left.Where(l => sub1.All(s => s.ID != l.ID))
のsub1,2,3までは何とか終わるが4,5つめになると全然返ってこなくなる。変数の内容を見ると遅延評価を即時実行しようとしてタイムアウトしてしまう状態。
評価を遅延させるために余計な処理をしているのか、非効率なやり方をしているのか。う〜む。