2009-04-04 10 views

Antwort

26

ich denke, es meistens ist das Abrufen der aktuellen Kultur des Threads.

Wenn Sie Marc-Test ändern, um diese Form von String.StartsWith zu verwenden:

Stopwatch watch = Stopwatch.StartNew(); 
    CultureInfo cc = CultureInfo.CurrentCulture; 
    for (int i = 0; i < LOOP; i++) 
    { 
     if (s1.StartsWith(s2, false, cc)) chk++; 
    } 
    watch.Stop(); 
    Console.WriteLine(watch.ElapsedMilliseconds + "ms; chk: " + chk); 

es kommt ein gutes Stück näher.

Wenn Sie s1.StartsWith(s2, StringComparison.Ordinal) verwenden, ist es viel schneller als mit CompareInfo.IsPrefix (abhängig von der CompareInfo natürlich). Auf meiner Box sind die Ergebnisse (nicht wissenschaftlich):

  • s1.StartsWith (s2): 6914ms
  • s1.StartsWith (s2, falsch, Kultur): 5568ms
  • compare.IsPrefix (s1, s2): 5200ms
  • s1.StartsWith (s2, StringComparison.Ordinal): 1393ms

Offensichtlich ist das, weil es wirklich nur an jedem Punkt 16 Bit-Integer Vergleich, das ist ziemlich billig. Wenn Sie nicht wollen kultursensitive Überprüfung, und Leistung ist Ihnen besonders wichtig, das ist die Überladung, die ich verwenden würde.

5

StartsWith Aufrufe IsPrefix intern. Es weist Kulturinformationen vor dem Aufruf von IsPrefix zu.

5

Gute Frage; für einen Test, die ich erhalten:

9156ms; chk: 50000000 
6887ms; chk: 50000000 

Prüfstand:

using System; 
using System.Diagnostics; 
using System.Globalization;  

class Program 
{ 
    static void Main() 
    { 
     string s1 = "abcdefghijklmnopqrstuvwxyz", s2 = "abcdefg"; 

     const int LOOP = 50000000; 
     int chk = 0; 
     Stopwatch watch = Stopwatch.StartNew(); 
     for (int i = 0; i < LOOP; i++) 
     { 
      if (s1.StartsWith(s2)) chk++; 
     } 
     watch.Stop(); 
     Console.WriteLine(watch.ElapsedMilliseconds + "ms; chk: " + chk); 

     chk = 0; 
     watch = Stopwatch.StartNew(); 

     CompareInfo ci = CultureInfo.CurrentCulture.CompareInfo; 
     for (int i = 0; i < LOOP; i++) 
     { 
      if (ci.IsPrefix(s1, s2)) chk++; 
     } 
     watch.Stop(); 
     Console.WriteLine(watch.ElapsedMilliseconds + "ms; chk: " + chk); 
    } 
} 
0

Überprüfen Sie die Quelle von IsPrefix. Die Sache ist - in einigen Fällen wird es langsamer sein als StartsWith, nur weil es StartsWith tatsächlich verwendet und wenig mehr Operationen ausführt.

[System.Security.SecuritySafeCritical] // auto-generated 
    public unsafe virtual bool IsPrefix(String source, String prefix, CompareOptions options) 
    { 
     if (source == null || prefix == null) { 
      throw new ArgumentNullException((source == null ? "source" : "prefix"), 
       Environment.GetResourceString("ArgumentNull_String")); 
     } 
     Contract.EndContractBlock(); 
     int prefixLen = prefix.Length; 

     if (prefixLen == 0) 
     { 
      return (true); 
     } 

     if (options == CompareOptions.OrdinalIgnoreCase) 
     { 
      return source.StartsWith(prefix, StringComparison.OrdinalIgnoreCase); 
     } 

     if (options == CompareOptions.Ordinal) 
     { 
      return source.StartsWith(prefix, StringComparison.Ordinal); 
     } 

     if ((options & ValidIndexMaskOffFlags) != 0) { 
      throw new ArgumentException(Environment.GetResourceString("Argument_InvalidFlag"), "options"); 
     } 


     // to let the sorting DLL do the call optimization in case of Ascii strings, we check if the strings are in Ascii and then send the flag RESERVED_FIND_ASCII_STRING to 
     // the sorting DLL API SortFindString so sorting DLL don't have to check if the string is Ascii with every call to SortFindString. 

     return (InternalFindNLSStringEx(
        m_dataHandle, m_handleOrigin, m_sortName, 
        GetNativeCompareFlags(options) | Win32Native.FIND_STARTSWITH | ((source.IsAscii() && prefix.IsAscii()) ? RESERVED_FIND_ASCII_STRING : 0), 
        source, source.Length, 0, prefix, prefix.Length) > -1); 
    }