2011-09-25 32 views
7

Estoy usando Visual Studio 2010 SP1, el marco de destino es 2.0, destino de la plataforma: cualquier CPU, probando con Windows 7 x64 SP1.Comportamiento de rendimiento extraño

Tengo un comportamiento de rendimiento extraño.

Sin un app.config, o con la siguiente app.config, que hace que mi programa se ejecute lentamente (espectáculos cronómetro ~ 0.11 s)

<?xml version="1.0"?> 
<configuration> 
    <startup > 
    <supportedRuntime version="v2.0.50727" /> 
    </startup> 
</configuration> 

La siguiente app.config hace que mis tiempos de ejecución de programas x5 más rápido (cronógrafo muestra ~ 0.02 s)

<?xml version="1.0"?> 
<configuration> 
    <startup > 
    <supportedRuntime version="v4.0.30319" sku=".NETFramework,Version=v4.0" /> 
    </startup> 
</configuration> 

Este es el código de programa de pruebas:

using System; 
using System.Collections.Generic; 
using System.Text; 
using System.Diagnostics; 

class Program 
{ 
    static void Main(string[] args) 
    { 
     Stopwatch sw = new Stopwatch(); 

     while (true) 
     { 
      sw.Reset(); 
      sw.Start(); 

      for (int i = 0; i < 1000000; i++) 
      { 
       "blablabla".IndexOf("ngrhotbegmhroes", StringComparison.OrdinalIgnoreCase); 
      } 

      Console.WriteLine(sw.Elapsed); 
     } 
    } 
} 

estoy sentado durante horas y no puede entender lo que está sucediendo aquí. ¿Tienes alguna idea?

+0

La propia clase System.String fue cambiado en .NET 4. Con un montón de trabajo sobre los bits de NLS en el CLR. No se puede esperar razonablemente resultados similares, solo esperanza. –

Respuesta

15

Parece que acaba de encontrar una situación en la que .NET 4 es mucho más rápido. De forma predeterminada, su aplicación se ejecuta con el marco para el que se creó. Cuando fuerza para utilizar .NET 4, es más rápido. Esa puede ser una mejora del compilador JIT que afecta su situación, o puede ser una mejora del marco, pero no debe sorprender que algunas cosas sean más rápidas en las versiones más nuevas.

(Por lo que vale, aumentaría el número de iteraciones que está cronometrando si fuera usted ... en mi caja en .NET 4, cada iteración es de solo 10ms, que en realidad no es una . gran medida de que prefiero punto de referencia para al menos un par de segundos)

(Y como Mitch, puedo confirmar que veo el mismo efecto)

EDIT:.. yo sólo he investigado esto un poco más lejos , y visto un efecto interesante ... Asumiré que estamos llamando haystack.IndexOf(needle, StringComparison.OrdinalIgnoreCase):

  • En .NET 2, los resultados son más o menos la misma sea grande la "aguja" es
  • En .NET 4:
    • needle Si es más grande que haystack (como por su ejemplo) .NET 4 es mucho más rápido que .NET 2
    • needle Si es del mismo tamaño que haystack, .NET 4 es un poco poco más lento que .NET 2
    • needle Si es menor que haystack, .NET 4 es mucho más lento que .NET 2

(Esta es mantener una prueba donde el primer carácter de needle nunca aparece en haystack, por cierto.)

+0

No debería "Cuando lo fuerce a usar .NET", lea "¿Cuándo lo fuerza a usar .NET ** 4 **"? – Ani

+0

@Ani: Vaya, sí, gracias. –

+4

"Si la aguja es más pequeña que el pajar, .NET 4 es mucho más lento": parece una optimización muy pobre. –

4

que acaba de ejecutar su punto de referencia con algunos retoques (que incluía más iteraciones y promedio), y puede confirmar que la versión de destino .NET 4.0 es de hecho 4-5 veces más rápida.

Así que presumiblemente IndexOf() se ha optimizado en .NET 4.0

3

OK, algunos puntos de referencia con la nueva VS11

n = 1000000; 
string haystack = "ngrhotbegmhroes"; 
string needle = "blablablablablablablablablangrhotbegmhrobla bla"; 

.NET 4.5 : 8 ms 
.NET 4.0 : 8 ms 
.NET 3.5 : 45 ms 
.NET 2.0 : 45 ms 

Así que estos primeros resultados confirman los hallazgos, las versiones más recientes son más rápidos.

Sin embargo, es mucho más común para buscar s corto de cuerda dentro de una cadena más grande:

n = 1000000; 
haystack = "blablablablablablablablablangrhotbegmhrobla bla"; 
needle = "ngrhotbegmhroes"; 

.NET 4.5 : 1020 ms 
.NET 4.0 : 1020 ms 
.NET 3.5 : 155 ms 
.NET 2.0 : 155 ms 

Y con un pajar mucho más largo (~ 400 caracteres)

.NET 4.0 : 12100 ms 
.NET 2.0 : 1700 ms 

Lo que significa que las cosas se pusieron peor para el patrón de uso más común ...


Todas las medidas en Release config, and Cl Perfil de la persona disponible.
Ejecución de VS 11 con Ctrl + F5
Win 7H, Core i7 2620M

+0

wow - esto es realmente extraño - me pregunto si algunos internos de la CLR/BCL podrían decir algo al respecto ... – Carsten

+0

¿Cuál es incluso el punto de buscar una aguja larga en un corto pajar? ¿No es esto FALSO por diseño? – yas4891

+0

@ yas4891: Sí, pero fue la pregunta original y tiene un rendimiento muy diferente. –