문제

이것은 단지 질문을 내 호기심을 충족하기 위해.그러나 저에게 그것은 흥미 롭습니다.

썼는데 이 작은 간단한 벤치마크입니다.그것은 3 개의 Regexp 에서 실행해 몇 천 번을:

기본적으로,내가 사용하는 동일한 패턴 하지만 다른 방법이 있습니다.

  1. 귀하의 일반적인 방법이 없 RegexOptions.시작과 함께.NET2.0 이러한되지 않을 얻을 캐시됩니다.하지만 이어야 한다"캐싱"기 때문에 그것은에서 개최 예쁜 글로벌 범위와 다시 설정되지 않습니다.

  2. RegexOptions.Compiled

  3. 으로 호출을 정적 Regex.Match(pattern, input) 는 않 캐시됩니다.NET2.0

는 코드는 다음과 같습니다:

static List<string> Strings = new List<string>();        
static string pattern = ".*_([0-9]+)\\.([^\\.])$";

static Regex Rex = new Regex(pattern);
static Regex RexCompiled = new Regex(pattern, RegexOptions.Compiled);

static Random Rand = new Random(123);

static Stopwatch S1 = new Stopwatch();
static Stopwatch S2 = new Stopwatch();
static Stopwatch S3 = new Stopwatch();

static void Main()
{
  int k = 0;
  int c = 0;
  int c1 = 0;
  int c2 = 0;
  int c3 = 0;

  for (int i = 0; i < 50; i++)
  {
    Strings.Add("file_"  + Rand.Next().ToString() + ".ext");
  }
  int m = 10000;
  for (int j = 0; j < m; j++)
  {
    c = Rand.Next(1, 4);

    if (c == 1)
    {
      c1++;
      k = 0;
      S1.Start();
      foreach (var item in Strings)
      {
        var m1 = Rex.Match(item);
        if (m1.Success) { k++; };
      }
      S1.Stop();
    }
    else if (c == 2)
    {
      c2++;
      k = 0;
      S2.Start();
      foreach (var item in Strings)
      {
        var m2 = RexCompiled.Match(item);
        if (m2.Success) { k++; };
      }
      S2.Stop();
    }
    else if (c == 3)
    {
      c3++;
      k = 0;
      S3.Start();
      foreach (var item in Strings)
      {
        var m3 = Regex.Match(item, pattern);
        if (m3.Success) { k++; };
      }
      S3.Stop();
    }
  }

  Console.WriteLine("c: {0}", c1);
  Console.WriteLine("Total milliseconds: " + (S1.Elapsed.TotalMilliseconds).ToString());
  Console.WriteLine("Adjusted milliseconds: " + (S1.Elapsed.TotalMilliseconds).ToString());

  Console.WriteLine("c: {0}", c2);
  Console.WriteLine("Total milliseconds: " + (S2.Elapsed.TotalMilliseconds).ToString());
  Console.WriteLine("Adjusted milliseconds: " + (S2.Elapsed.TotalMilliseconds*((float)c2/(float)c1)).ToString());

  Console.WriteLine("c: {0}", c3);
  Console.WriteLine("Total milliseconds: " + (S3.Elapsed.TotalMilliseconds).ToString());
  Console.WriteLine("Adjusted milliseconds: " + (S3.Elapsed.TotalMilliseconds*((float)c3/(float)c1)).ToString());
}

때마다 나는 그것은 결과가의 라인을 따라:

    Not compiled and not automatically cached:
    Total milliseconds: 6185,2704
    Adjusted milliseconds: 6185,2704

    Compiled and not automatically cached:
    Total milliseconds: 2562,2519
    Adjusted milliseconds: 2551,56949184038

    Not compiled and automatically cached:
    Total milliseconds: 2378,823
    Adjusted milliseconds: 2336,3187176891

그래서 당신이 그것을 가지고있습니다.지 않지만,그 약 7~8%차이입니다.

그것은 신비이다.I 할 수 없는 이유를 설명하는 첫 번째 방법은 것은 훨씬 느리기 때문에 그것은 결코 다시는 평가지에서 개최된 글로벌 정적 변수입니다.

방법으로,이것입니다.Net3.5 고 모노 2.2 는 행동을 정확히 동일합니다.응용 프로그램을 시작합니다.

그래서,어떤 아이디어,왜 컴파일된 변형도 뒤쳐?

EDIT1:

후에 코드를 수정 결과는 지금과 같습니다:

    Not compiled and not automatically cached:
    Total milliseconds: 6456,5711
    Adjusted milliseconds: 6456,5711

    Compiled and not automatically cached:
    Total milliseconds: 2668,9028
    Adjusted milliseconds: 2657,77574842168

    Not compiled and automatically cached:
    Total milliseconds: 6637,5472
    Adjusted milliseconds: 6518,94897724836

는 더 이상 사용하지 않는 다른 모든 질문 뿐만 아니라.

답변 감사합니다.

도움이 되었습니까?

해결책

regex.match 버전에서 패턴의 입력을 찾고 있습니다. 주위에 매개 변수를 교환 해보십시오.

var m3 = Regex.Match(pattern, item); // Wrong
var m3 = Regex.Match(item, pattern); // Correct

다른 팁

비슷한 행동입니다.또한 이유를 궁금해 컴파일된 버전이 느리고,하지만 주는 위의 특정 번호를 통화,컴파일된 버전이 더 빠릅니다.그래서 나는 파 반사체 약간의,그리고 주를 위한 컴파일된 Regex,아직 약간의 설정에 대해 수행하는 첫 번째 통화(특히,인스턴스를 만들의 적절한 RegexRunner object).

내에서 테스트,내가 찾는다면 내가 모두 이동 생성자 및 초기 버리는 전화 regex 외부 타이머를 시작하고,컴파일된 regex won 방법에 상관없이 여러 번 반복했다.


덧붙여,캐싱하는 프레임워크는 일을 사용하는 경우 정적 Regex 방법은 최적화의 유일한 필요할 때 사용하여 정적 Regex 방법이 있습니다.이 때문에 모든 호출을 정적 Regex 방법을 새로 생성 Regex 체입니다.에 Regex 클래스의 생성해야 분석 패턴이다.캐시할 수 있습한 후속 호출의 정적 Regex 방법 사용 RegexTree 분석에서 첫 번째 호출하는 것을 방지하여 구문 분석하는 단계입니다.

을 사용할 때 인스턴스에 대한 방법의 단일 Regex 체,다음이 문제가 되지 않습니다.이 분석은 여전히 중 하나를 수행 시간(객체를 작성할 때).또한,당신은 당신을 얻을 방지하기 위해 다른 모든 코드를 생성자뿐만 아니라 힙 할당(및 후속 가비지 컬렉션).

마틴 Brown 는 반전 인수하는 귀하의 정적 Regex 전화(좋은 캐치,마틴).난 당신을 찾는 경우 수정하는 인스턴스지 않는(컴파일)regex 이길 것입 정적 매번 호출합니다.당신은 또한 찾을 수 있는,나의 결과를 위,컴파일된 인스턴스에서 이길지 않은 컴파일된다.

:당신이 정말로 읽 Jeff 우주의 게시물 에 컴파일된 정규표현식에 당신이 가기 전에는 맹목적으로 적용하는 옵션을 모든 정규 표현식을 만듭니다.

동일한 패턴을 사용하여 동일한 문자열과 지속적으로 일치하는 경우 캐시 된 버전이 컴파일 된 버전보다 약간 빠른 이유를 설명 할 수 있습니다.

이것은 문서에서 나온 것입니다.

https://msdn.microsoft.com/en-us/library/gg578045(v=vs.110).aspx

A. 정적 정규 표현 메소드가 호출되고 캐시에서는 정규 표현식을 찾을 수 없습니다. 정규식 엔진은 정규 표현식을 일련의 작동 코드로 변환하여 캐시에 저장합니다.. 그런 다음 JIT 컴파일러가 실행할 수 있도록 이러한 작동 코드를 MSIL로 변환합니다. 해석 된 정규 표현식은 실행 시간이 느려지는 비용으로 시작 시간을 줄입니다.. 이 때문에 그들은 그렇습니다 정규 표현식이 소수의 메소드 호출에 사용될 때 가장 잘 사용됩니다., 또는 정규 표현 방법에 대한 정확한 호출 수가 알려져 있지 않지만 작을 것으로 예상되는 경우. 메소드 호출 수가 증가함에 따라 시작 시간 감소의 성능 게인은 실행 속도가 느려집니다.

해석 된 정규 표현과 달리 컴파일 된 정규 표현식은 시작 시간을 증가 시키지만 개별 패턴 매칭 방법을 더 빨리 실행합니다.. 결과적으로, 정규 표현식을 컴파일함으로써 발생하는 성능 이점은 호출 된 정규 표현 방법의 수에 비례하여 증가합니다.


요약하려면 사용하는 것이 좋습니다 해석 된 정규 표현 특정 정규 표현식으로 정규 표현 방법을 호출 할 때 비교적 드물게.

당신은 사용해야합니다 정규 표현식을 편집했습니다 특정 정규 표현식으로 정규 표현 방법을 호출 할 때 비교적 자주 발생합니다.


감지하는 방법?

해석 된 정규 표현식의 느린 실행 속도가 감소 된 시작 시간의 이득보다 높거나 컴파일 된 정규 표현식의 느린 시작 시간이 더 빠른 실행 속도의 이익보다 큰 임계 값이 결정하기가 어렵습니다. 그것은 정규 표현의 복잡성과 그것이 처리하는 특정 데이터를 포함하여 다양한 요인에 의존합니다. 해석 또는 컴파일 정규 표현식이 특정 응용 프로그램 시나리오에 대한 최상의 성능을 제공하는지 여부를 결정하려면 STOPWATCH 클래스를 사용하여 실행 시간을 비교할 수 있습니다..


정규 표현식 편집 :

다음 상황에서 정기적 인 표현식을 조립품에 컴파일하는 것이 좋습니다.

  1. 재사용 가능한 정규식 라이브러리를 만들고자하는 구성 요소 개발자 인 경우.
  2. 정규 표현식의 패턴 매칭 방법을 불확실한 횟수로 한 번 또는 두 번에서 수천 번 또는 수만 번이라고 기대하는 경우. 컴파일 또는 해석 된 정규 표현식과 달리, 어셈블리를 별도의 어셈블리로 편집하는 정규식은 메소드 호출 수에 관계없이 일관된 성능을 제공합니다.
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top