2009-04-04 15 views

Respuesta

26

Creo que sobre todo ir a buscar la cultura actual del hilo.

Si cambia la prueba de Marc a utilizar esta forma de String.StartsWith:

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

se trata de mucho más cerca.

Si utiliza s1.StartsWith(s2, StringComparison.Ordinal) Es mucho más rápido que usar CompareInfo.IsPrefix (dependiendo de la CompareInfo por supuesto). En mi caja de los resultados son (no científico):

  • s1.StartsWith (S2): 6914ms
  • s1.StartsWith (S2, falsa, cultura): 5568ms
  • compare.IsPrefix (S1, S2): 5200ms
  • s1.StartsWith (s2, StringComparison.Ordinal): 1393ms

Obviamente eso es porque no deja de ser la comparación de enteros de 16 bits en cada punto, que es bastante barato. Si no desea quiere una verificación sensible a la cultura, y el rendimiento es particularmente importante para usted, esa es la sobrecarga que usaría.

5

StartsCon llamadas internas de IsPrefix. Asigna información cultural antes de llamar a IsPrefix.

5

Buena pregunta; para una prueba, consigo: Plataforma

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

prueba:

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

Consulte la fuente de IsPrefix. El problema es que, en algunos casos, va a ser más lento que StartsWith solo porque realmente usa StartsWith y hace pocas operaciones más.

[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); 
    } 
Cuestiones relacionadas