質問
1つの要素についてリストを頻繁に検索する必要があるコードベースを使用しています。
リストで列挙を手動で行うよりもPredicateとFind()を使用する方が高速ですか?
例:
string needle = "example";
FooObj result = _list.Find(delegate(FooObj foo) {
return foo.Name == needle;
});
対
string needle = "example";
foreach (FooObj foo in _list)
{
if (foo.Name == needle)
return foo;
}
機能的には同等ですが、パフォーマンスも同等ですか?
解決
これらはパフォーマンスが同等ではありません。 Find()メソッドには、リスト内のすべてのアイテムに対するメソッド(この場合はデリゲート)呼び出しが必要です。メソッドの呼び出しは無料ではなく、インライン比較と比較して比較的高価です。 foreachバージョンでは、オブジェクトごとにメソッドを呼び出す必要はありません。
そうは言っても、実際にコードのプロファイルを作成し、これが問題になるまでは、パフォーマンスに基づいてどちらかを選択することはありません。このシナリオのオーバーヘッドがすべて「ホットパス」であることはまだわかりません。私が書いたコードの問題であり、私はこのパターンをFindや他の同様の方法でよく使います。
他のヒント
リストの検索が現状のままでは遅すぎる場合、おそらく線形検索よりも優れている可能性があります。リストのソートを維持できる場合は、バイナリ検索を使用してO(lg n)時間で要素を見つけることができます。
全体ロットを検索する場合は、そのリストを辞書に置き換えて、オブジェクトを名前でインデックス付けすることを検討してください。
技術的には、デリゲートバージョンの実行時パフォーマンスは他のバージョンよりもわずかに劣りますが、ほとんどの場合、違いを知覚するのは難しいでしょう。
より重要なのは(IHMO)、コードの実行時のパフォーマンスではなく、必要な方法ではなく、必要なものを作成できることです。これにより、保守性に大きな違いが生じます。
この元のコード:
string needle = "example";
foreach (FooObj foo in _list)
{
if (foo.Name == needle)
return foo;
}
コードを読み、特定のアイテムを探していることを理解するためにメンテナーが必要です。
このコード
string needle = "example";
return _list.Find(
delegate(FooObj foo)
{
return foo.Name == needle;
});
特定のアイテムを探していることを明確にします-より早く理解します。
最後に、C#3.0の機能を使用したこのコード:
string needle = "example";
return _list.Find( foo => foo.Name == needle);
はまったく同じことをしますが、1行で読みやすく理解しやすくなります(ラムダ式、とにかく)。
要約すると、代替のパフォーマンスがほぼ等しいことを考えると、コードを読みやすく保守しやすいものを選択してください。
" 1つの要素についてリストを頻繁に検索する必要があるコードベースを使用しています
パフォーマンスを向上させるには、データ構造をListではなくDictionaryに変更することをお勧めします
List.ForEach対foreach-iteration( foreach vs someList.Foreach()について同様の質問が行われました。 {} )。
その場合、List.ForEachは少し速くなりました。
Jaredが指摘したように、違いがあります。
しかし、いつものように、それがボトルネックであることを知らない限り心配しないでください。そして、それがボトルネックである場合、それはおそらくリストが大きいためです、その場合は、より速い検索を使用することを検討する必要があります-ハッシュテーブルまたはバイナリツリー、または単にリストをソートしてバイナリ検索を行うことでlog(n)線形ケースを微調整するよりもはるかに大きな影響を与えるパフォーマンス。