Является ли String.Contains() быстрее, чем String.IndexOf()?
У меня есть строковый буфер длиной около 2000 символов и нужно проверить буфер, если он содержит определенную строку.
Будет выполнять проверку в ASP.NET 2.0 webapp для каждого веб-запроса.
Кто-нибудь знает, работает ли метод 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);
Забавный факт
Ответы
Ответ 1
Contains
вызывает IndexOf
:
public bool Contains(string value)
{
return (this.IndexOf(value, StringComparison.Ordinal) >= 0);
}
Что вызывает CompareInfo.IndexOf
, который в конечном итоге использует реализацию CLR.
Если вы хотите посмотреть, как строки сравниваются в CLR это покажет вам (ищите CaseInsensitiveCompHelper).
IndexOf(string)
не имеет параметров, а Contains()
использует сравнительное сравнение (побайтовое сравнение вместо попыток выполнить интеллектуальное сравнение, например e с помощью é).
Итак, IndexOf
будет немного быстрее (теоретически), поскольку IndexOf
переходит прямо в строковый поиск, используя FindNLSString из kernel32.dll(мощность рефлектора!).
Обновлено для .NET 4.0. IndexOf больше не использует сравнительное сравнение, поэтому Contains может быть быстрее. См. Комментарий ниже.
Ответ 2
Возможно, это не имеет значения. Читайте этот пост в Coding Horror;): http://www.codinghorror.com/blog/archives/001218.html
Ответ 3
Содержит (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).
Содержит в моих тестах ту же производительность, что и IndexOf (s2, StringComparison.Ordinal) >= 0, но она короче и делает ваше намерение понятным.
Ответ 4
Используя Reflector, вы можете видеть, что Contains реализуется с помощью IndexOf. Здесь реализация.
public bool Contains(string value)
{
return (this.IndexOf(value, StringComparison.Ordinal) >= 0);
}
Содержит, скорее всего, немного медленнее, чем прямое обращение к IndexOf, но я сомневаюсь, что это будет иметь какое-то значение для реальной производительности.
Ответ 5
Я запускаю реальный случай (в отличие от синтетического теста)
if("=,<=,=>,<>,<,>,!=,==,".IndexOf(tmps)>=0) {
против
if("=,<=,=>,<>,<,>,!=,==,".Contains(tmps)) {
Это жизненно важная часть моей системы, и она выполнена 131,953 раза (спасибо DotTrace).
Однако шокирующий сюрприз, результат - это то, что ожидалось
- IndexOf 533ms.
- Содержит 266 мс.
: -/
net framework 4.0 (обновлено по состоянию на 13-02-2012)
Ответ 6
Если вы действительно хотите оптимизировать свой микрокомпьютер, ваш лучший подход - это всегда бенчмаркинг.
Структура .net имеет отличную реализацию секундомера - System.Diagnostics.Stopwatch
Ответ 7
Так же, как обновление к этому, я проводил некоторое тестирование и предоставляю вашу входную строку довольно большой, а затем параллельный Regex - это самый быстрый метод С#, который я нашел (при условии, что у вас есть более одного ядра, которое я себе представляю)
Получение общего количества совпадений, например -
needles.AsParallel ( ).Sum ( l => Regex.IsMatch ( haystack , Regex.Escape ( l ) ) ? 1 : 0 );
Надеюсь, это поможет!
Ответ 8
Используйте эталонную библиотеку, например этот недавний набег от Jon Skeet для ее измерения.
Как и все (микро-) вопросы производительности, это зависит от версий используемого программного обеспечения, деталей проверенных данных и кода, связанного с вызовом.
Как и все (микро-) вопросы производительности, первым шагом должно быть получение текущей версии, которая легко поддерживается. Тогда бенчмаркинг, профилирование и настройка могут быть применены к измеренным узким местам, а не гадать.
Ответ 9
Из небольшого чтения видно, что под капотом метод String.Contains просто вызывает String.IndexOf. Разница заключается в String.Contains возвращает логическое значение, а String.IndexOf возвращает целое число с (-1), представляющее, что подстрока не была найдена.
Я бы посоветовал написать небольшой тест со 100 000 итерационными итерациями и убедиться в этом сами. Если бы я догадался, я бы сказал, что IndexOf может быть немного быстрее, но, как я сказал, это просто предположение.
У Джеффа Этвуда есть хорошая статья о струнах в его блоге. Это больше о конкатенации, но может быть полезно, тем не менее.
Ответ 10
Для тех, кто все еще читает это, indexOf(), вероятно, лучше работает на большинстве корпоративных систем, так как contains() несовместим с IE!