2010-09-22 11 views
6

Wyjaśnię mój problem (przepraszam mój zły angielski), mam .NET exe, w którym każda milisekunda przetwarzania jest bardzo ważna.Porównywanie ciągów w ramce dotnet 4

Ten program wykonuje wiele porównań łańcuchowych (większość z nich to string1.IndexOf(string2, StringComparison.OrdinalIgnoreCase)).

Po przejściu na platformę 4 mój czas programu jest dwa razy niż poprzednio.

Szukałem wyjaśnienia i stwierdziłem, że funkcja IndexOf(s, OrdinalIgnoreCase) jest znacznie wolniejsza w ramce 4 (testowałem z prostą aplikacją konsolową, a w czasie pętli czas wyniósł 30 ms w 3.5 i 210 ms w 4.0 ???). Ale porównanie w obecnej kulturze jest szybsze w ramach 4 niż 3.5.

tu to przykładowy kod używam:

int iMax = 100000; 
String str = "Mozilla/5.0+(Windows;+U;+Windows+NT+5.1;+fr;+rv:1.9.0.1)+Gecko/2008070208+Firefox/3.0.1"; 
Stopwatch sw = new Stopwatch(); 
sw.Start(); 
StringComparison s = StringComparison.OrdinalIgnoreCase; 
for(int i = 1;i<iMax;i++) 
{ 
    str.IndexOf("windows", s); 
} 
sw.Stop(); 
Console.WriteLine(sw.ElapsedMilliseconds); 
Console.Read(); 

moje pytania są następujące:

  1. Czy ktoś zauważył ten sam problem?

  2. Ktoś ma wyjaśnienie tej zmiany?

  3. Czy istnieje rozwiązanie pozwalające ominąć problem?

Dzięki.

+0

Czy parametry ciągu są oparte na typach znaków lub typach ciągów znaków? – ChrisBD

+0

Parametry struny – baz

Odpowiedz

5

Ok Mam odpowiedź na jedno z moich pytań.

Z reflektorem widzę różnicę między ramami 2 i 4, które wyjaśniają mój problem z perforatorią.

public int IndexOf(string value, int startIndex, int count, StringComparison comparisonType) 
{ 
    if (value == null) 
    { 
     throw new ArgumentNullException("value"); 
    } 
    if ((startIndex < 0) || (startIndex > this.Length)) 
    { 
     throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index")); 
    } 
    if ((count < 0) || (startIndex > (this.Length - count))) 
    { 
     throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_Count")); 
    } 
    switch (comparisonType) 
    { 
     case StringComparison.CurrentCulture: 
      return CultureInfo.CurrentCulture.CompareInfo.IndexOf(this, value, startIndex, count, CompareOptions.None); 

     case StringComparison.CurrentCultureIgnoreCase: 
      return CultureInfo.CurrentCulture.CompareInfo.IndexOf(this, value, startIndex, count, CompareOptions.IgnoreCase); 

     case StringComparison.InvariantCulture: 
      return CultureInfo.InvariantCulture.CompareInfo.IndexOf(this, value, startIndex, count, CompareOptions.None); 

     case StringComparison.InvariantCultureIgnoreCase: 
      return CultureInfo.InvariantCulture.CompareInfo.IndexOf(this, value, startIndex, count, CompareOptions.IgnoreCase); 

     case StringComparison.Ordinal: 
      return CultureInfo.InvariantCulture.CompareInfo.IndexOf(this, value, startIndex, count, CompareOptions.Ordinal); 

     case StringComparison.OrdinalIgnoreCase: 
      return TextInfo.IndexOfStringOrdinalIgnoreCase(this, value, startIndex, count); 
    } 
    throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), "comparisonType"); 
} 

Jest to kod bazowy funkcji IndexOf ram 2 (bez różnicy pomiędzy 4 i 2)

Ale w funkcji TextInfo.IndexOfStringOrdinalIgnoreCase istnieją różnice:

Framework 2:

internal static unsafe int IndexOfStringOrdinalIgnoreCase(string source, string value, int startIndex, int count) 
{ 
    if (source == null) 
    { 
     throw new ArgumentNullException("source"); 
    } 
    return nativeIndexOfStringOrdinalIgnoreCase(InvariantNativeTextInfo, source, value, startIndex, count); 
} 

Framework 4:

internal static int IndexOfStringOrdinalIgnoreCase(string source, string value, int startIndex, int count) 
{ 
    if ((source.Length == 0) && (value.Length == 0)) 
    { 
     return 0; 
    } 
    int num = startIndex + count; 
    int num2 = num - value.Length; 
    while (startIndex <= num2) 
    { 
     if (CompareOrdinalIgnoreCaseEx(source, startIndex, value, 0, value.Length, value.Length) == 0) 
     { 
      return startIndex; 
     } 
     startIndex++; 
    } 
    return -1; 
} 

Algorytm główny zmieniło się w ramach 2 odbierane jest nativeDll który został usunięty z ram 4. Jest dobrze wiedzieć

0

Nie mogę odpowiedzieć na temat konkretnego problemu z .NET 4 prędkości.

Prawdopodobnie jednak uzyskasz znacznie większą prędkość, dzięki poprawiając swoje algo. Sprawdź numer Rabin-Karp string search algo.

+0

Tak, mogę użyć innego algo, ale chcę wiedzieć, dlaczego framework 4 jest wolniejszy niż framework 2. Sprawdzam karabin-rabina dzięki – baz

+0

Nie mogę powiedzieć, że z niektórych punktów mówi się, że jest szybszy. Być może na innych jest wolniej. – Wernight