String.Contains()はString.IndexOf()より高速ですか?


111

約2000文字の文字列バッファがあり、特定の文字列が含まれているかどうかバッファを確認する必要があります。
すべてのWebリクエストに対してASP.NET 2.0 Webアプリケーションでチェックを行います。

String.ContainsメソッドString.IndexOfメソッドよりもパフォーマンスが良いかどうか誰かが知っていますか?

    // 2000 characters in s1, search token in s2
    string s1 = "Many characters. The quick brown fox jumps over the lazy dog"; 
    string s2 = "fox";
    bool b;
    b = s1.Contains(s2);
    int i;
    i = s1.IndexOf(s2);

楽しい事実


14
これをWebリクエストごとに10億回実行する必要がある場合、私はこのようなものを検討し始めます。それ以外の場合は、どちらの方法で費やされた時間も、最初にHTTPリクエストを受信する場合と比較して、信じられないほど重要ではないので、気にしません。
mookid8000 2009年

2
最適化の鍵の1つは、.NETのバージョン、オペレーティングシステム、ハードウェア、入力のバリエーションなどの多くの要因に依存する可能性があるため、想定する代わりにテストすることです。多くの場合、他の人が行ったテスト結果ご使用のシステムでは、非常に異なる場合があります。
Slai

回答:


174

Contains呼び出しIndexOf

public bool Contains(string value)
{
    return (this.IndexOf(value, StringComparison.Ordinal) >= 0);
}

これはCompareInfo.IndexOf、最終的にCLR実装を使用するを呼び出します。

CLRで文字列が比較される方法を確認する場合は、これが表示されますCaseInsensitiveCompHelperを探します)。

IndexOf(string)オプションはなくContains()、序数比較を使用します(たとえば、eとéでスマート比較を実行するのではなく、バイトごとの比較)。

そのため、kernel32.dllからFindNLSStringを使用して文字列検索を直接実行IndexOfすると(理論的には)わずかに高速になります(IndexOfリフレクターの能力です)。

.NET 4.0用に更新 - IndexOfメソッドは、もはや序の比較を使用しないので、高速になりますが含まれています。以下のコメントを参照してください。


3
この答えはほぼ正確ではありません。説明については、こちらのstackoverflow.com/posts/498880/revisionsをご覧ください
pzaj

55
私の答えは7歳で、.NET 2フレームワークに基づいています。バージョン4は、IndexOf()実際に使用していますStringComparison.CurrentCultureし、Contains()用途にStringComparison.Ordinal速くなります。しかし、実際に私たちが話している速度の違いはほんのわずかです-要点は一方が他方を呼び出すことであり、インデックスが必要ない場合は、Containsの方が読みやすくなります。つまり、心配する必要はありません。
Chris S、

21

おそらく、それはまったく問題ではないでしょう。コーディングホラーに関するこの投稿を読んでください ;):http : //www.codinghorror.com/blog/archives/001218.html


4
ボスに吸い付くのは…?:Dあなたは正しいですが、httpリクエストを処理するのにかかる時間と比較して、短い文字列を1回検索することは重要ではありません。
家禽

非常に面白い読みですが、連結に関する彼の最初の不満はメモリ使用量であり、文字列を組み合わせるさまざまな方法で費やされた時間をテストするだけです。
sab669 2013年

11

Contains(s2)はIndexOf(s2)よりも何倍も(私のコンピューターでは10倍)高速です。これは、ContainsがStringComparison.Ordinalを使用するためです。 //davesbox.com/archive/2008/11/12/breaking-changes-to-the-string-class.aspx)。

私のテストでは、ContainsはIndexOf(s2、StringComparison.Ordinal)> = 0とまったく同じパフォーマンスを持っていますが、これは短く、意図を明確にします。


2
.NET 4.0での変更はRTMに移行する
Stephen Kennedy

7

私は実際のケースを実行しています(合成ベンチマークとは反対に)

 if("=,<=,=>,<>,<,>,!=,==,".IndexOf(tmps)>=0) {

 if("=,<=,=>,<>,<,>,!=,==,".Contains(tmps)) {

これは私のシステムの重要な部分であり、131,953回実行されます(DotTraceに感謝)。

しかし、驚きにショックを与えると、結果は予想と反対であります

  • IndexOf 533ms。
  • 266msを含みます。

:-/

ネットフレームワーク4.0(13-02-2012のように更新)


1
ので、INTよりはるかに大きいBOOL、とIndexOf>=0一歩の原因
エリック・殷

3
「StringComparison.Ordinal」を使用するのを忘れていました
Davi Fiamenghi 2013年

6

Reflectorを使用すると、ContainsがIndexOfを使用して実装されていることがわかります。これが実装です。

public bool Contains(string value)
{
   return (this.IndexOf(value, StringComparison.Ordinal) >= 0);
}

つまり、Containsは、IndexOfを直接呼び出すよりも少し遅くなる可能性がありますが、実際のパフォーマンスに意味があるとは思えません。


1
はい。ただし、indexofをブール値として使用するには、関数の外部で比較を行う必要があります。それはおそらくContainsと同じ結果をもたらすでしょうね?
ゴンザロクエロ

1
おそらく、1つのメソッド呼び出しを保存します(インライン化できない場合を除く)。私が言ったように、それはおそらく重要ではありません。
ブライアンラスムッセン

6

コードをマイクロ最適化したい場合、最善のアプローチは常にベンチマークです。

.netフレームワークは、優れたストップウォッチ実装を備えています-System.Diagnostics.Stopwatch


最善の方法ですが、迅速なアプローチ必要な場合は、デバッグセッションで一時停止ボタンを押してください。コードコントロールは、時間の約50%で最も遅い部分で停止する可能性があります。
Jeremy Thompson、

4

少し読むと、内部ではString.Containsメソッドは単にString.IndexOfを呼び出しているように見えます。違いは、String.Containsはブール値を返しますが、String.IndexOfは、サブストリングが見つからなかったことを表す(-1)の整数を返します。

100,000ほどの反復で小さなテストを作成し、自分で確認することをお勧めします。私が推測したとしたら、IndexOfは少し速いかもしれないと言いますが、私が言ったように、それは単なる推測です。

ジェフ・アトウッドは彼のブログで弦についての良い記事を持っています。それは連結についてですが、それでもなお役立つかもしれません。


3

これに対する更新と同じように、私はいくつかのテストを行って、入力文字列を提供するのがかなり大きいので、並列Regexは私が見つけた最速のC#メソッドです(私が想像しているコアが複数ある場合)

たとえば、一致の総数を取得する-

needles.AsParallel ( ).Sum ( l => Regex.IsMatch ( haystack , Regex.Escape ( l ) ) ? 1 : 0 );

お役に立てれば!


1
こんにちは別のスレッドのphildがこれを phildがtomasp.net/articles/ahocorasick.aspxの。キーワード(針)が変更されないようにすると、はるかに速くなります。
ゲイリー、

2

Jon Skeetによる最近の進出のように、ベンチマークライブラリを使用して測定します。

買い手責任負担

すべての(マイクロ)パフォーマンスに関する質問と同様に、これは、使用しているソフトウェアのバージョン、検査されるデータの詳細、および呼び出しを取り巻くコードによって異なります。

すべての(マイクロ)パフォーマンスの質問と同様に、最初のステップは、簡単に保守できる実行中のバージョンを取得することです。その後、ベンチマーク、プロファイリング、およびチューニングを、推測する代わりに、測定されたボトルネックに適用できます。


このリンクで質問に答えることができますが、回答の重要な部分をここに含め、参照用のリンクを提供することをお勧めします。リンクされたページが変更されると、リンクのみの回答が無効になる可能性があります。
マイクストックデール2014年

リンクされたライブラリは多くの1つにすぎず、答えの主な目的ではありません。ライブラリのソースまたは説明を投稿しても、このサイトまたは世界の答えが改善されるとは思いません。
デビッドシュミット2014年

3
-1; 問題は、「String.ContainsメソッドがString.IndexOfメソッドよりもパフォーマンスが良いかどうかを誰かが知っているか」ということでした。-あなたの答えは「ベンチマークライブラリを使用する」です。これは基本的に「わからない、自分でやる」、「これは場合によって異なります」、「わからない」、「実行中のバージョンとプロファイルを取得する」という意味です。 、「わからない、自分でやる」という意味です。これは「Jeopardy」ではありません。ハウツーのアイデアではなく、質問への回答 提供しください-彼らの場所はコメントにあります

-7

これをまだ読んでいる人にとっては、contains()はIEと互換性がないため、indexOf()はほとんどのエンタープライズシステムでおそらくより良いパフォーマンスを発揮します。


12
新しいOutOfScopeException();をスローします。
ラファエル
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.