Mam bufor ciągów o długości około 2000 znaków i muszę sprawdzić bufor, jeśli zawiera określony ciąg.
Dokonuje sprawdzenia w aplikacji internetowej ASP.NET 2.0 dla każdego żądania internetowego.
Czy ktoś wie, czy metoda String.Contains działa lepiej niż metoda 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);
Odpowiedzi:
Contains
wywołaniaIndexOf
:Które wywołania
CompareInfo.IndexOf
, które ostatecznie używają implementacji CLR.Jeśli chcesz zobaczyć, jak ciągi są porównywane w środowisku CLR, to pokaże Ci (poszukaj CaseInsensitiveCompHelper ).
IndexOf(string)
nie ma opcji iContains()
używa porównania porządkowego (porównanie bajt po bajcie, zamiast próbować przeprowadzić inteligentne porównanie, na przykład e z é).Więc
IndexOf
będzie nieznacznie szybszy (w teorii), ponieważIndexOf
przechodzi bezpośrednio do wyszukiwania ciągów za pomocą FindNLSString z kernel32.dll (moc reflektora!).Zaktualizowano dla .NET 4.0 - IndexOf nie używa już porządkowego porównania, więc zawartość może być szybsza. Zobacz komentarz poniżej.
źródło
IndexOf()
rzeczywiście używaStringComparison.CurrentCulture
iContains()
używa,StringComparison.Ordinal
które będą szybsze. Ale tak naprawdę różnice w szybkości, o których mówimy, są niewielkie - chodzi o to, że jedno wywołuje drugie, a zawartość jest bardziej czytelna, jeśli nie potrzebujesz indeksu. Innymi słowy, nie martw się o to.Prawdopodobnie nie będzie to miało żadnego znaczenia. Przeczytaj ten post na Coding Horror;): http://www.codinghorror.com/blog/archives/001218.html
źródło
Contains (s2) jest wiele razy (na moim komputerze 10 razy) szybsze niż IndexOf (s2), ponieważ Contains używa StringComparison.Ordinal, które jest szybsze niż wyszukiwanie uwzględniające kulturę, które domyślnie wykonuje IndexOf (ale może się zmienić w .net 4.0 http: //davesbox.com/archive/2008/11/12/breaking-changes-to-the-string-class.aspx ).
Contains ma dokładnie taką samą wydajność jak IndexOf (s2, StringComparison.Ordinal)> = 0 w moich testach, ale jest krótszy i jasno określa twój zamiar.
źródło
Prowadzę prawdziwy przypadek (w przeciwieństwie do syntetycznego benchmarku)
przeciw
Jest to istotna część mojego systemu i jest wykonywana 131 953 razy (dzięki DotTrace).
Jakkolwiek szokująca niespodzianka , wynik jest odwrotny od oczekiwanego
: - /
net framework 4.0 (aktualizacja na dzień 13-02-2012)
źródło
INT
jest znacznie większy niżBOOL
iIndexOf>=0
powoduje jeszcze jeden krokUżywając Reflectora, możesz zobaczyć, że Contains jest zaimplementowany przy użyciu IndexOf. Oto implementacja.
Więc Contains jest prawdopodobnie trochę wolniejsze niż bezpośrednie wywołanie IndexOf, ale wątpię, czy będzie miało to jakiekolwiek znaczenie dla rzeczywistej wydajności.
źródło
Jeśli naprawdę chcesz mikrooptymalizować swój kod, najlepszym podejściem jest zawsze benchmarking.
Framework .net ma doskonałą implementację stopera - System.Diagnostics.Stopwatch
źródło
Z krótkiego czytania wynika, że pod maską metoda String.Contains po prostu wywołuje String.IndexOf. Różnica polega na tym, że String.Contains zwraca wartość logiczną, podczas gdy String.IndexOf zwraca liczbę całkowitą, w której (-1) oznacza, że podłańcuch nie został znaleziony.
Proponuję napisać mały test z około 100 000 iteracjami i przekonaj się sam. Gdybym miał zgadywać, powiedziałbym, że IndexOf może być nieco szybszy, ale tak jak powiedziałem, to tylko przypuszczenie.
Jeff Atwood ma na swoim blogu dobry artykuł o sznurkach . Chodzi bardziej o konkatenację, ale może być pomocna.
źródło
Tak jak aktualizacja tego, przeprowadziłem testy i podałem, że ciąg wejściowy jest dość duży, a równoległe Regex jest najszybszą metodą C #, jaką znalazłem (pod warunkiem, że masz więcej niż jeden rdzeń, jaki sobie wyobrażam)
Na przykład uzyskanie całkowitej liczby dopasowań -
Mam nadzieję że to pomoże!
źródło
Skorzystaj z biblioteki wzorcowej, takiej jak ta niedawna wyprawa Jona Skeeta, aby to zmierzyć.
Caveat Emptor
Podobnie jak w przypadku wszystkich (mikro) pytań dotyczących wydajności, zależy to od wersji używanego oprogramowania, szczegółów sprawdzanych danych i kodu otaczającego wywołanie.
Jak w przypadku wszystkich pytań dotyczących (mikro) wydajności, pierwszym krokiem musi być uzyskanie działającej wersji, która będzie łatwa w utrzymaniu. Następnie zamiast zgadywania można zastosować benchmarking, profilowanie i dostrajanie do zmierzonych wąskich gardeł.
źródło
Dla każdego, kto nadal to czyta, indexOf () prawdopodobnie będzie działać lepiej w większości systemów korporacyjnych, ponieważ funkcja include () nie jest kompatybilna z IE!
źródło