with starts net endswith asp and .net performance string startswith

.net - net - ¿Por qué la función es un prefijo más rápido que Startswith en C#?



string contains vb net (4)

Buena pregunta; para una prueba, me sale:

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

Banco de pruebas:

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

¿Alguien sabe por qué la función StartsWith C # (.NET) es considerablemente más lenta que IsPrefix ?


Comienza con llamadas a IsPrefix internamente. Asigna información de cultura antes de llamar a IsPrefix.


Creo que es principalmente recuperar la cultura actual del hilo.

Si cambia la prueba de Marc para usar 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 acerca mucho mas

Si usa s1.StartsWith(s2, StringComparison.Ordinal) es mucho más rápido que usar CompareInfo.IsPrefix (según la CompareInfo de CompareInfo por supuesto). En mi caja los resultados son (no científicamente):

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

Obviamente, eso se debe a que en realidad solo se comparan enteros de 16 bits en cada punto, lo cual es bastante barato. Si no desea una verificación sensible a la cultura, y el rendimiento es particularmente importante para usted, esa es la sobrecarga que usaría.


Echa un vistazo a la fuente de IsPrefix. El problema es que, en algunos casos, será más lento que StartsWith solo porque en realidad usa StartsWith y realiza 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); }