2010-09-22 22 views
6

Spiegherò il mio problema (scusa il mio pessimo inglese), ho un exe .NET in cui ogni millisecondo di elaborazione è molto importante.Confronto di stringhe in framework dotnet 4

Questo programma esegue molte comparazioni di stringhe (la maggior parte è string1.IndexOf(string2, StringComparison.OrdinalIgnoreCase)).

Quando passo al framework 4, l'orario del mio programma è due volte rispetto a prima.

Ho cercato una spiegazione e ho trovato che la funzione IndexOf(s, OrdinalIgnoreCase) è molto più lenta nel framework 4 (ho provato con una semplice applicazione di console e in un ciclo il tempo era 30ms in 3.5 e 210ms in 4.0 ???). Ma il confronto nella cultura attuale è più veloce nel quadro 4 di 3.5.

Qui è un esempio di codice che uso:

int iMax = 100000; 
String str = "Mozilla/5.0+(Windows;+U;+Windows+NT+5.1;+fr;+rv:1.9.0.1)+Gecko/2008070208+Firefox/3.0.1"; 
Stopwatch sw = new Stopwatch(); 
sw.Start(); 
StringComparison s = StringComparison.OrdinalIgnoreCase; 
for(int i = 1;i<iMax;i++) 
{ 
    str.IndexOf("windows", s); 
} 
sw.Stop(); 
Console.WriteLine(sw.ElapsedMilliseconds); 
Console.Read(); 

Le mie domande sono:

  1. Qualcuno ha notato lo stesso problema?

  2. Qualcuno ha una spiegazione su questo cambiamento?

  3. Esiste una soluzione per aggirare il problema?

Grazie.

+0

I parametri delle stringhe sono basati su tipi char o tipi di stringhe? – ChrisBD

+0

parametri stringa – baz

risposta

5

Ok, ho una risposta a una delle mie domande.

Con il riflettore posso vedere la differenza tra le strutture 2 e 4 e questo spiega il mio problema di perforamnce.

public int IndexOf(string value, int startIndex, int count, StringComparison comparisonType) 
{ 
    if (value == null) 
    { 
     throw new ArgumentNullException("value"); 
    } 
    if ((startIndex < 0) || (startIndex > this.Length)) 
    { 
     throw new ArgumentOutOfRangeException("startIndex", Environment.GetResourceString("ArgumentOutOfRange_Index")); 
    } 
    if ((count < 0) || (startIndex > (this.Length - count))) 
    { 
     throw new ArgumentOutOfRangeException("count", Environment.GetResourceString("ArgumentOutOfRange_Count")); 
    } 
    switch (comparisonType) 
    { 
     case StringComparison.CurrentCulture: 
      return CultureInfo.CurrentCulture.CompareInfo.IndexOf(this, value, startIndex, count, CompareOptions.None); 

     case StringComparison.CurrentCultureIgnoreCase: 
      return CultureInfo.CurrentCulture.CompareInfo.IndexOf(this, value, startIndex, count, CompareOptions.IgnoreCase); 

     case StringComparison.InvariantCulture: 
      return CultureInfo.InvariantCulture.CompareInfo.IndexOf(this, value, startIndex, count, CompareOptions.None); 

     case StringComparison.InvariantCultureIgnoreCase: 
      return CultureInfo.InvariantCulture.CompareInfo.IndexOf(this, value, startIndex, count, CompareOptions.IgnoreCase); 

     case StringComparison.Ordinal: 
      return CultureInfo.InvariantCulture.CompareInfo.IndexOf(this, value, startIndex, count, CompareOptions.Ordinal); 

     case StringComparison.OrdinalIgnoreCase: 
      return TextInfo.IndexOfStringOrdinalIgnoreCase(this, value, startIndex, count); 
    } 
    throw new ArgumentException(Environment.GetResourceString("NotSupported_StringComparison"), "comparisonType"); 
} 

Questo è il codice di base della funzione IndexOf del quadro 2 (nessuna differenza tra 4 e 2)

Ma nella funzione TextInfo.IndexOfStringOrdinalIgnoreCase ci sono differenze:

quadro 2:

internal static unsafe int IndexOfStringOrdinalIgnoreCase(string source, string value, int startIndex, int count) 
{ 
    if (source == null) 
    { 
     throw new ArgumentNullException("source"); 
    } 
    return nativeIndexOfStringOrdinalIgnoreCase(InvariantNativeTextInfo, source, value, startIndex, count); 
} 

Framework 4:

internal static int IndexOfStringOrdinalIgnoreCase(string source, string value, int startIndex, int count) 
{ 
    if ((source.Length == 0) && (value.Length == 0)) 
    { 
     return 0; 
    } 
    int num = startIndex + count; 
    int num2 = num - value.Length; 
    while (startIndex <= num2) 
    { 
     if (CompareOrdinalIgnoreCaseEx(source, startIndex, value, 0, value.Length, value.Length) == 0) 
     { 
      return startIndex; 
     } 
     startIndex++; 
    } 
    return -1; 
} 

L'algoritmo principale è cambiato nel quadro 2 la chiamata è una nativeDll che è stato rimosso del quadro 4. Il suo bene sapere

0

Non riesco a rispondere al problema specifico della velocità .NET 4.

Tuttavia, probabilmente aumenterai di molto la velocità di migliorando il tuo algo. Controlla il Rabin-Karp string search algo.

+0

Sì, posso usare un altro algo, ma voglio sapere perché framework 4 è più lento del framework 2. Vedo il Rabin-Karp grazie – baz

+0

Non posso dire che da alcuni punti è stato detto che è più veloce. Può essere che sia più lento per gli altri. – Wernight