2011-09-25 29 views
7

Utilizzo Visual Studio 2010 SP1, Target framework è 2.0, Target della piattaforma: Qualsiasi CPU, test in Windows 7 x64 SP1.Strano comportamento delle prestazioni

Sto sperimentando un comportamento strano delle prestazioni.

Senza un app.config, o con il seguente app.config, rende il mio programma di corsa lenta (spettacoli cronometro ~ 0.11 s)

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

Il seguente app.config rende i miei tempi di esecuzione del programma x5 più veloce (cronometro mostra ~ 0,02 s)

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

Questo è il codice programma di test:

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

sono seduto per ore e non riesco a capire cosa sta succedendo qui. Hai qualche idea?

+0

La classe System.String si cambiò in .NET 4. Con abbondanza di lavoro sui bit NLS del CLR. Non puoi ragionevolmente aspettarti risultati simili, solo speranza. –

risposta

15

Sembra che tu abbia appena trovato una situazione in cui .NET 4 è molto più veloce. Per impostazione predefinita, la tua app è in esecuzione con il framework che è stato creato per il targeting. Quando si forza per utilizzare .NET 4, è più veloce. Potrebbe trattarsi di un miglioramento del compilatore JIT che potrebbe colpire la tua situazione, o potrebbe essere un miglioramento della struttura - ma non dovrebbe essere troppo sorprendente che alcune cose siano più veloci nelle versioni più recenti.

(Per quel che vale, aumenterei il numero di iterazioni su cui avresti cronometrato se fossi in te ... sul mio box sotto .NET 4, ogni iterazione è a soli 10ms, che non è proprio un . grande misura preferisco punto di riferimento per almeno un paio di secondi)

(E come Mitch, posso confermare che vedo lo stesso effetto)

EDIT:.. ho appena studiato ulteriormente questo un po ' e ho visto un effetto interessante ... presumo che stiamo chiamando haystack.IndexOf(needle, StringComparison.OrdinalIgnoreCase):

  • On. NET 2, i risultati sono più o meno lo stesso per quanto grande la "ago" è
  • On .NET 4:
    • Se needle è più grande di haystack (secondo il vostro esempio) .NET 4 è molto più veloce di .NET 2
    • Se needle è la stessa dimensione di haystack, .NET 4 è un po po 'più lento rispetto NET 2
    • Se needle è più piccolo haystack, .NET 4 è un molto più lento di .NET 2

(Ciò sta mantenendo un test in cui il primo carattere del needle non appare mai in haystack, btw.)

+0

Non dovrebbe "Quando lo forzate ad usare .NET" leggi "Quando lo forzate ad usare .NET ** 4 **"? – Ani

+0

@Ani: Oops, sì, grazie. –

+4

"Se ago è più piccolo del pagliaio, .NET 4 è molto più lento" - sembra quindi un'ottimizzazione molto scarsa. –

4

Ho appena eseguito il punto di riferimento con un paio di modifiche (che comprendeva più iterazioni e media), e posso confermare che la versione di destinazione di .NET 4.0 è infatti 4-5 volte più veloce.

Quindi presumibilmente IndexOf() è stato ottimizzato in .NET 4.0

3

OK, alcuni parametri di riferimento con il nuovo 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 

Così questi primi risultati confermano le vostre scoperte, le versioni più recenti sono più veloci.

Tuttavia è molto più comune per cercare s breve stringa all'interno di una stringa più 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 

E con un pagliaio molto più lungo (~ 400 caratteri)

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

Il che significa che le cose sono andate peggio per il modello di utilizzo più comune ...


Tutte le misure in Config di rilascio, e Cl Profilo di ient dove disponibile.
Che va dal VS 11 con Ctrl + F5
Win 7H, Core i7 2620m

+0

wow - questo è davvero strano - mi chiedo se alcuni interni al CLR/BCL potrebbero dire qualcosa su questo ... – Carsten

+0

Qual è anche il punto di cercare un ago lungo in un breve pagliaio? Non è questo FALSO dal design? – yas4891

+0

@ yas4891: Sì, ma era la domanda originale e ha prestazioni molto diverse. –