Является ли String.Contains () быстрее, чем String.IndexOf ()? - PullRequest
108 голосов
/ 31 января 2009

У меня есть строковый буфер около 2000 символов, и мне нужно проверить буфер, если он содержит определенную строку.
Выполняет проверку в веб-приложении ASP.NET 2.0 для каждого веб-запроса.

Кто-нибудь знает, работает ли метод 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);

Забавный факт

Ответы [ 10 ]

160 голосов
/ 31 января 2009

Contains звонки IndexOf:

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

, который вызывает CompareInfo.IndexOf, который в конечном итоге использует реализацию CLR.

Если вы хотите увидеть, как строки сравниваются в CLR , это покажет вам (ищите CaseInsensitiveCompHelper ).

IndexOf(string) не имеет опций, а Contains() использует Порядковое сравнение (побайтовое сравнение, а не попытка выполнить интеллектуальное сравнение, например, с é).

Таким образом, IndexOf будет незначительно быстрее (теоретически), поскольку IndexOf сразу перейдет к поиску строки с использованием FindNLSString из kernel32.dll (мощность отражателя!).

Обновлено для .NET 4.0 - IndexOf больше не использует Порядковое сравнение, поэтому Contains может быть быстрее. См. Комментарий ниже.

20 голосов
/ 31 января 2009

Наверное, это не будет иметь никакого значения. Прочитайте этот пост на Coding Horror;): http://www.codinghorror.com/blog/archives/001218.html

11 голосов
/ 31 января 2009

Contains (s2) во много раз (на моем компьютере в 10 раз) быстрее, чем IndexOf (s2), потому что Contains использует StringComparison.Ordinal, который работает быстрее, чем поиск с учетом культуры, который IndexOf выполняет по умолчанию (но может измениться в .net 4,0 http://davesbox.com/archive/2008/11/12/breaking-changes-to-the-string-class.aspx).

Contains имеет точно такую ​​же производительность, как IndexOf (s2, StringComparison.Ordinal)> = 0 в моих тестах, но оно короче и проясняет ваши намерения.

7 голосов
/ 14 марта 2012

Я использую реальный случай (в отличие от синтетического теста)

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

против

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

Это жизненно важная часть моей системы, и она выполняется 131 953 раза (спасибо DotTrace).

Однако шокирующий сюрприз , результат противоположен ожидаемому

  • IndexOf 533ms.
  • Содержит 266 мс.

: - /

net framework 4.0 (обновлено по состоянию на 13-02-2012)

6 голосов
/ 31 января 2009

Используя Reflector, вы можете видеть, что Contains реализован с использованием IndexOf. Вот реализация.

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

Так что Contains, вероятно, немного медленнее, чем прямой вызов IndexOf, но я сомневаюсь, что это будет иметь какое-то значение для фактической производительности.

5 голосов
/ 31 января 2009

Если вы действительно хотите микрооптимизировать свой код, ваш лучший подход - это всегда бенчмаркинг.

.NET Framework имеет отличную реализацию секундомера - System.Diagnostics.Stopwatch

3 голосов
/ 16 апреля 2010

В качестве обновления к этому я проводил некоторое тестирование и предоставлял вашу входную строку довольно большой, тогда как параллельный Regex - самый быстрый метод C #, который я нашел (при условии, что у вас есть более одного ядра, я думаю)

Получение общего количества совпадений, например -

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

Надеюсь, это поможет!

3 голосов
/ 31 января 2009

Из небольшого прочтения видно, что под капотом метод String.Contains просто вызывает String.IndexOf. Разница в том, что String.Contains возвращает логическое значение, а String.IndexOf возвращает целое число с (-1), представляющее, что подстрока не была найдена.

Я бы предложил написать небольшой тест с примерно 100 000 итераций и убедиться в этом. Если бы я угадал, я бы сказал, что IndexOf может быть немного быстрее, но, как я уже сказал, это всего лишь предположение.

У Джеффа Этвуда есть хорошая статья о строках в его блоге . Это больше о конкатенации, но, тем не менее, может быть полезным.

2 голосов
/ 31 января 2009

Используйте библиотеку тестов, например , это недавнее набег от Джона Скита , чтобы измерить его.

Предостережение Emptor

Как и все (микро) вопросы производительности, это зависит от версий программного обеспечения, которое вы используете, деталей проверенных данных и кода, связанного с вызовом.

Как и все (микро) вопросы производительности, первым шагом должно быть получение работающей версии, которую легко поддерживать. Затем к измеренным узким местам можно применять бенчмаркинг, профилирование и настройку, а не гадать.

0 голосов
/ 12 февраля 2016

Для тех, кто все еще читает это, indexOf (), вероятно, будет работать лучше в большинстве корпоративных систем, так как метод содержит () не совместим с IE!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...