Is String.Contains() faster than String.IndexOf()?

C#.Netasp.netPerformanceString

C# Problem Overview


I have a string buffer of about 2000 characters and need to check the buffer if it contains a specific string.
Will do the check in a ASP.NET 2.0 webapp for every webrequest.

Does anyone know if the String.Contains method performs better than String.IndexOf method?

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

Fun fact

C# Solutions


Solution 1 - C#

Contains calls IndexOf:

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

Which calls CompareInfo.IndexOf, which ultimately uses a CLR implementation.

If you want to see how strings are compared in the CLR this will show you (look for CaseInsensitiveCompHelper).

IndexOf(string) has no options and Contains()uses an Ordinal compare (a byte-by-byte comparison rather than trying to perform a smart compare, for example, e with é).

So IndexOf will be marginally faster (in theory) as IndexOf goes straight to a string search using FindNLSString from kernel32.dll (the power of reflector!).

Updated for .NET 4.0 - IndexOf no longer uses Ordinal Comparison and so Contains can be faster. See comment below.

Solution 2 - C#

Contains(s2) is many times (in my computer 10 times) faster than IndexOf(s2) because Contains uses StringComparison.Ordinal that is faster than the culture sensitive search that IndexOf does by default (but that may change in .net 4.0 http://davesbox.com/archive/2008/11/12/breaking-changes-to-the-string-class.aspx).

Contains has exactly the same performance as IndexOf(s2,StringComparison.Ordinal) >= 0 in my tests but it's shorter and makes your intent clear.

Solution 3 - C#

I am running a real case (in opposite to a synthetic benchmark)

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

versus

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

It is a vital part of my system and it is executed 131,953 times (thanks DotTrace).

However shocking surprise, the result is the opposite that expected

  • IndexOf 533ms.
  • Contains 266ms.

:-/

net framework 4.0 (updated as for 13-02-2012)

Solution 4 - C#

By using Reflector, you can see, that Contains is implemented using IndexOf. Here's the implementation.

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

So Contains is likely a wee bit slower than calling IndexOf directly, but I doubt that it will have any significance for the actual performance.

Solution 5 - C#

If you really want to micro optimise your code your best approach is always benchmarking.

The .net framework has an excellent stopwatch implementation - System.Diagnostics.Stopwatch

Solution 6 - C#

From a little reading, it appears that under the hood the String.Contains method simply calls String.IndexOf. The difference is String.Contains returns a boolean while String.IndexOf returns an integer with (-1) representing that the substring was not found.

I would suggest writing a little test with 100,000 or so iterations and see for yourself. If I were to guess, I'd say that IndexOf may be slightly faster but like I said it just a guess.

Jeff Atwood has a good article on strings at his blog. It's more about concatenation but may be helpful nonetheless.

Solution 7 - C#

Just as an update to this I've been doing some testing and providing your input string is fairly large then parallel Regex is the fastest C# method I've found (providing you have more than one core I imagine)

Getting the total amount of matches for example -

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

Hope this helps!

Solution 8 - C#

Tried it today on a 1.3 GB text file. Amongst others every line is checked for existence of a '@' char. 17.000.000 calls to Contains/IndexOf are made. Result: 12.5 sec for all Contains('@') calls, 2.5 sec for all IndexOf('@') calls. => IndexOf performs 5 times faster!! (.Net 4.8)

Solution 9 - C#

Use a benchmark library, like this recent foray from Jon Skeet to measure it.

Caveat Emptor

As all (micro-)performance questions, this depends on the versions of software you are using, the details of the data inspected and the code surrounding the call.

As all (micro-)performance questions, the first step has to be to get a running version which is easily maintainable. Then benchmarking, profiling and tuning can be applied to the measured bottlenecks instead of guessing.

Solution 10 - C#

For anyone still reading this, indexOf() will probably perform better on most enterprise systems, as contains() is not compatible with IE!

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionKb.View Question on Stackoverflow
Solution 1 - C#Chris SView Answer on Stackoverflow
Solution 2 - C#ggf31416View Answer on Stackoverflow
Solution 3 - C#magallanesView Answer on Stackoverflow
Solution 4 - C#Brian RasmussenView Answer on Stackoverflow
Solution 5 - C#Andrew HarryView Answer on Stackoverflow
Solution 6 - C#Mike RoosaView Answer on Stackoverflow
Solution 7 - C#garyView Answer on Stackoverflow
Solution 8 - C#CSharperView Answer on Stackoverflow
Solution 9 - C#David SchmittView Answer on Stackoverflow
Solution 10 - C#ZargontapelView Answer on Stackoverflow