wake-up-neo.net

Ist String.Contains () schneller als String.IndexOf ()?

Ich habe einen Zeichenkettenpuffer von ungefähr 2000 Zeichen und muss den Puffer überprüfen, wenn er eine bestimmte Zeichenkette enthält.
Überprüft für jede Webanforderung eine ASP.NET 2.0-Webanwendung.

Weiß jemand, ob die String.Contains-Methode eine bessere Leistung erzielt als String.IndexOf-Methode ?

    // 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);

lustige Tatsache

109
Kb.

Contains ruft IndexOf auf:

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

Welcher ruft CompareInfo.IndexOf Auf, der letztendlich eine CLR-Implementierung verwendet.

Wenn Sie sehen möchten, wie Zeichenfolgen in der CLR verglichen werden dies wird Ihnen zeigen (suchen Sie nach CaseInsensitiveCompHelper).

IndexOf(string) hat keine Optionen und Contains() verwendet einen Ordinalvergleich (einen byteweisen Vergleich, anstatt zu versuchen, einen intelligenten Vergleich durchzuführen, z. B. e mit é).

Also wird IndexOf (theoretisch) geringfügig schneller sein, da IndexOf direkt mit FindNLSString von kernel32.dll zu einer Zeichenfolgensuche übergeht (die Kraft des Reflektors!).

Aktualisiert für .NET 4.0 - IndexOf verwendet nicht mehr den Ordinalvergleich und kann daher schneller sein. Siehe Kommentar unten.

166
Chris S

Wahrscheinlich wird es überhaupt keine Rolle spielen. Lesen Sie diesen Beitrag über Coding Horror;): http://www.codinghorror.com/blog/archives/001218.html

20
Gonzalo Quero

Contains (s2) ist um ein Vielfaches (in meinem Computer um das Zehnfache) schneller als IndexOf (s2), da Contains StringComparison.Ordinal verwendet, das schneller ist als die kulturabhängige Suche, die IndexOf standardmäßig durchführt (dies kann sich jedoch in .net 4.0 ändern). http://davesbox.com/archive/2008/11/12/breaking-changes-to-the-string-class.aspx ).

Contains hat in meinen Tests genau die gleiche Leistung wie IndexOf (s2, StringComparison.Ordinal)> = 0, ist jedoch kürzer und verdeutlicht Ihre Absicht.

11
ggf31416

Ich leite einen echten Fall (im Gegensatz zu einem synthetischen Benchmark)

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

versus

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

Es ist ein wichtiger Teil meines Systems und wird 131.953 Mal ausgeführt (danke DotTrace).

Aber schockierende Überraschung, das Ergebnis ist das Gegenteil von dem, was man erwartet

  • IndexOf 533ms.
  • Enthält 266ms.

: - /

net framework 4.0 (aktualisiert am 13-02-2012)

7
magallanes

Mit Reflector können Sie sehen, dass Contains mit IndexOf implementiert ist. Hier ist die Implementierung.

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

Contains ist also wahrscheinlich etwas langsamer als der direkte Aufruf von IndexOf, aber ich bezweifle, dass es für die tatsächliche Leistung von Bedeutung sein wird.

6
Brian Rasmussen

Wenn Sie Ihren Code wirklich mikrooptimieren möchten, ist Benchmarking immer Ihr bester Ansatz.

Das .net-Framework verfügt über eine hervorragende Stoppuhr-Implementierung - System.Diagnostics.Stopwatch

6
Andrew Harry

Nach einigem Lesen scheint es, dass die String.Contains-Methode unter der Haube einfach String.IndexOf aufruft. Der Unterschied ist, dass String.Contains einen booleschen Wert zurückgibt, während String.IndexOf eine Ganzzahl mit (-1) zurückgibt, die angibt, dass die Teilzeichenfolge nicht gefunden wurde.

Ich würde vorschlagen, einen kleinen Test mit etwa 100.000 Iterationen zu schreiben und es selbst zu sehen. Wenn ich raten würde, würde ich sagen, dass IndexOf vielleicht etwas schneller ist, aber wie ich schon sagte, es ist nur eine Vermutung.

Jeff Atwood hat einen guten Artikel über Streicher unter sein Blog . Es geht mehr um Verkettung, kann aber trotzdem hilfreich sein.

3
Mike Roosa

Gerade als Update habe ich einige Tests durchgeführt und angegeben, dass Ihre Eingabezeichenfolge ziemlich groß ist, dann ist Regex die schnellste C # -Methode, die ich gefunden habe (vorausgesetzt, Sie haben mehr als einen Kern, den ich mir vorstelle).

So erhalten Sie beispielsweise die Gesamtanzahl der Übereinstimmungen:

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

Hoffe das hilft!

3
gary

Verwenden Sie eine Benchmark-Bibliothek wie dieser jüngste Vorstoß von Jon Skeet , um sie zu messen.

Vorbehalt Emptor

Wie bei allen (Mikro-) Leistungsfragen hängt dies von den Versionen der von Ihnen verwendeten Software, den Details der überprüften Daten und dem Code ab, der den Anruf umgibt.

Wie bei allen (Mikro-) Performance-Fragen muss der erste Schritt darin bestehen, eine lauffähige Version zu erhalten, die leicht zu warten ist. Dann können Benchmarking, Profiling und Tuning auf die gemessenen Engpässe angewendet werden, anstatt zu raten.

2
David Schmitt