String.Contains ()가 String.IndexOf ()보다 빠릅니까?


111

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

재미있는 사실


14
웹 요청 당 수십억 번이 작업을 수행해야한다면 이와 같은 것을 살펴보기 시작합니다. 다른 경우에는 두 방법 중 하나에 소요되는 시간이 처음에 HTTP 요청을 수신하는 것에 비해 매우 중요하지 않을 가능성이 높으므로 신경 쓰지 않을 것입니다.
mookid8000

2
최적화의 핵심 중 하나는 가정하는 대신 테스트하는 것입니다. .NET 버전, 운영 체제, 하드웨어, 입력 변동 등과 같은 많은 요인에 따라 달라질 수 있기 때문입니다. 많은 경우 다른 사용자가 수행 한 테스트 결과 시스템에서 매우 다를 수 있습니다.
Slai

답변:


174

Contains전화 IndexOf:

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

CompareInfo.IndexOf궁극적으로 CLR 구현을 사용 하는를 호출합니다 .

CLR에서 문자열을 비교하는 방법을 확인하려는 경우 표시됩니다 ( CaseInsensitiveCompHelper 검색 ).

IndexOf(string)옵션이 없으며 Contains()서수 비교 (예 : e와 é와 같이 스마트 비교를 수행하는 대신 바이트 단위 비교)를 사용합니다.

따라서 kernel32.dll에서 FindNLSString을 사용하는 문자열 검색 (반사기의 힘!)으로 곧바로 이동 IndexOf하므로 이론 상으로는 약간 더 빠릅니다 IndexOf.

.NET 4.0 업데이트 - 같이 IndexOf는 더 이상 서수 비교를 사용하지 않습니다 그래서 빠를 수 있습니다 포함되어 있습니다. 아래 주석을 참조하십시오.


3
이 답변은 거의 정확하지 않습니다. 여기 에서 설명을 참조하십시오. stackoverflow.com/posts/498880/revisions
pzaj

55
내 대답은 7 살이며 .NET 2 프레임 워크를 기반으로합니다. 버전 4 IndexOf()는 실제로 사용 StringComparison.CurrentCulture하고 Contains()사용합니다 StringComparison.Ordinal. 그러나 실제로 우리가 말하는 속도 차이는 아주 미미합니다. 요점은 하나가 다른 하나를 호출한다는 것입니다. 인덱스가 필요하지 않으면 Contains가 더 읽기 쉽습니다. 즉, 그것에 대해 걱정하지 마십시오.
Chris S

21

아마도 그것은 전혀 중요하지 않을 것입니다. Coding Horror에서이 게시물 읽기;) : http://www.codinghorror.com/blog/archives/001218.html


4
상사에게 빠는 우리는 ...? : D하지만 http 요청을 처리하는 데 걸리는 시간에 비해 짧은 문자열을 한 번 검색하는 것은 중요하지 않습니다.
Fowl

매우 재미있는 읽기이지만 연결에 대한 그의 초기 불만은 메모리 사용이며, 문자열을 결합하는 다양한 방법으로 보낸 시간에 대해서만 테스트합니다.
sab669

11

Contains (s2)는 IndexOf (s2)보다 여러 배 (내 컴퓨터에서 10 배) 더 빠릅니다. Contains는 IndexOf가 기본적으로 수행하는 문화권 감지 검색보다 빠른 StringComparison.Ordinal을 사용하기 때문입니다 (하지만 .net 4.0에서 변경 될 수 있음 http : //davesbox.com/archive/2008/11/12/breaking-changes-to-the-string-class.aspx ).

포함은 내 테스트에서 IndexOf (s2, StringComparison.Ordinal)> = 0과 정확히 동일한 성능을 갖지만 더 짧고 의도를 명확하게합니다.


2
.NET 4.0의 변경 사항은 RTM으로 전환되기 전에 분명히 되돌려 졌으므로
Stephen Kennedy

7

실제 사례를 실행 중입니다 (합성 벤치 마크와 반대)

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

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

그것은 내 시스템의 중요한 부분이며 131,953 번 실행됩니다 (DotTrace에게 감사드립니다).

그러나 충격적인 놀라움 , 결과는 예상과 반대입니다.

  • IndexOf 533ms.
  • 266ms를 포함합니다.

:-/

net framework 4.0 (2012 년 2 월 13 일 업데이트 됨)


1
때문에이 INT보다 훨씬 더 큰 BOOL, 그리고 IndexOf>=0한 단계 원인
에릭 음

3
당신은 'StringComparison.Ordinal' 사용하는 것을 잊었다
다비 Fiamenghi

6

Reflector를 사용하면 포함이 IndexOf를 사용하여 구현되었음을 알 수 있습니다. 다음은 구현입니다.

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

따라서 포함은 IndexOf를 직접 호출하는 것보다 약간 느릴 수 있지만 실제 성능에 어떤 의미가 있을지 의심됩니다.


1
예,하지만 indexof를 부울로 사용하려면 함수 외부에서 비교를 수행해야합니다. 포함과 동일한 결과를 얻을 가능성이 큽니다.
Gonzalo Quero

1
아마도,하지만 당신은 하나의 메서드 호출을 저장합니다 (인라인 될 수없는 경우). 내가 말했듯이 그것은 아마도 결코 중요하지 않을 것입니다.
Brian Rasmussen

6

코드를 마이크로 최적화하려면 항상 벤치마킹하는 것이 가장 좋습니다.

.net 프레임 워크에는 뛰어난 스톱워치 구현이 있습니다 -System.Diagnostics.Stopwatch


가장 좋지만 빠른 접근을 원한다면 디버그 세션에서 일시 중지 버튼을 누르십시오. 코드 제어는 약 50 %의 가장 느린 부분에서 중단 될 가능성이 높습니다 .
Jeremy Thompson

4

조금 읽어 보면 String.Contains 메서드가 단순히 String.IndexOf를 호출하는 것으로 보입니다. 차이점은 String.Contains는 부울을 반환하는 반면 String.IndexOf는 (-1)이 하위 문자열을 찾을 수 없음을 나타내는 정수를 반환한다는 것입니다.

100,000 회 정도의 반복으로 작은 테스트를 작성하고 직접 확인하는 것이 좋습니다. 내가 추측한다면 IndexOf가 약간 더 빠를 수 있지만 내가 말한 것처럼 그냥 추측이라고 말하고 싶습니다.

Jeff Atwood는 그의 블로그 에서 문자열에 대한 좋은 기사를 가지고 있습니다 . 연결에 관한 것이지만 그럼에도 불구하고 도움이 될 수 있습니다.


3

이것에 대한 업데이트와 마찬가지로 몇 가지 테스트를 수행하고 입력 문자열이 상당히 큰 경우 병렬 Regex가 내가 찾은 가장 빠른 C # 방법입니다 (상상하는 코어가 둘 이상인 경우)

예를 들어 총 일치 수 얻기-

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

도움이 되었기를 바랍니다!


1
별도의 스레드에서 안녕하세요 phild는 tomasp.net/articles/ahocorasick.aspx 의 버전으로 업데이트했습니다. 키워드 (바늘)가 변경되지 않는 것이 훨씬 더 빠릅니다.
gary 2010-04-17

2

Jon Skeet의 최근 발표 와 같은 벤치 마크 라이브러리를 사용 하여 측정하십시오.

경고 Emptor

모든 (마이크로) 성능 질문과 같이 이것은 사용중인 소프트웨어 버전, 검사 한 데이터의 세부 정보 및 통화를 둘러싼 코드에 따라 다릅니다.

모든 (마이크로) 성능 문제와 마찬가지로 첫 번째 단계는 쉽게 유지 관리 할 수있는 실행중인 버전을 얻는 것입니다. 그런 다음 벤치마킹, 프로파일 링 및 튜닝을 추측하는 대신 측정 된 병목 현상에 적용 할 수 있습니다.


이 링크가 질문에 답할 수 있지만 여기에 답변의 필수 부분을 포함하고 참조 용 링크를 제공하는 것이 좋습니다. 링크 된 페이지가 변경되면 링크 전용 답변이 무효화 될 수 있습니다.
Mike Stockdale 2014 년

연결된 라이브러리는 많은 것 중 하나 일 뿐이며 대답의 주요 요지는 아닙니다. 나는 도서관 소스 나 설명을 게시하는 것이이 사이트 나 세상에 대한 답을 개선 할 것이라고 생각하지 않습니다.
David Schmitt

3
-1 ; 질문은 "String.Contains 메서드가 String.IndexOf 메서드보다 성능이 더 좋은지 아는 사람이 있습니까?"였습니다. -귀하의 대답은 "벤치 마크 라이브러리 사용"입니다. 기본적으로 "모르겠습니다. 직접 해보십시오", "이에 따라 다릅니다", "모름", "실행중인 버전 및 프로필 가져 오기"를 의미합니다. , 이는 "모르다, 직접해라"를 의미하기도합니다. 이것은 'Jeopardy'가 아닙니다. 방법에 대한 아이디어가 아니라 질문에 대한 답변 제공하세요 . 그 자리는 댓글에 있습니다.

-7

아직도 이것을 읽고있는 사람이라면, contains ()가 IE와 호환되지 않기 때문에 indexOf ()는 아마도 대부분의 기업 시스템에서 더 잘 수행 될 것입니다!


12
throw new OutOfScopeException ();
Raphaël
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.