2010-04-21 12 views
1

J'ai ce code, que lors de l'échange de l'ordre de UsingAs et UsingCast, leur performance permute également.Comment invalider le cache lors de l'analyse comparative?

using System; 
using System.Diagnostics; 
using System.Linq; 

using System.IO; 

class Test 
{ 
    const int Size = 30000000; 

    static void Main() 
    { 
     object[] values = new MemoryStream[Size]; 



     UsingAs(values); 
     UsingCast(values); 


     Console.ReadLine(); 
    } 

    static void UsingCast(object[] values) 
    { 
     Stopwatch sw = Stopwatch.StartNew(); 
     int sum = 0; 
     foreach (object o in values) 
     { 
      if (o is MemoryStream) 
      { 
       var m = (MemoryStream)o; 
       sum += (int)m.Length; 
      } 
     } 
     sw.Stop(); 
     Console.WriteLine("Cast: {0} : {1}", sum, 
          (long)sw.ElapsedMilliseconds); 
    } 

    static void UsingAs(object[] values) 
    { 
     Stopwatch sw = Stopwatch.StartNew(); 
     int sum = 0; 
     foreach (object o in values) 
     { 

      if (o is MemoryStream) 
      { 
       var m = o as MemoryStream; 
       sum += (int)m.Length; 
      } 
     } 
     sw.Stop(); 
     Console.WriteLine("As: {0} : {1}", sum, 
          (long)sw.ElapsedMilliseconds); 
    } 


} 

Sorties:

As: 0 : 322 
Cast: 0 : 281 

Quand vous faites cela ...

UsingCast(values); 
UsingAs(values); 

... Résultats: à ce

Cast: 0 : 322 
As: 0 : 281 

Quand vous faites tout ça ...

UsingAs(values); 

... Résultats: à ce

As: 0 : 322 

Quand vous faites ceci:

UsingCast(values); 

... Résultats: à ce

Cast: 0 : 322 

Mis à part les exécuter indépendamment, comment invalider le cache si th Le deuxième code étant évalué ne recevra pas la mémoire mise en cache du premier code?

Benchmarking côté, juste aimé le fait que les processeurs modernes font la magie de la mise en cache :-)

[EDIT]

Comme conseillé d'essayer ce code plus rapide (soi-disant) ...

static void UsingAsAndNullTest(object[] values) 
{   
    Stopwatch sw = Stopwatch.StartNew(); 
    int sum = 0; 
    foreach (object o in values) 
    { 
     var m = o as MemoryStream; 
     if (m != null) 
     {     
      sum += (int)m.Length; 
     } 
    } 
    sw.Stop(); 
    Console.WriteLine("As and null test: {0} : {1}", sum, 
         (long)sw.ElapsedMilliseconds); 
} 

... Le résultat est le suivant:

As and null test: 0 : 342 

Plus lent que les deux codes ci-dessus

[EDIT]:

Comme conseillé de la main de routine chacun leur propre copie ...

static void UsingAs(object[] values) 
{ 
    object[] a = values.ToArray(); 

    Stopwatch sw = Stopwatch.StartNew(); 
    int sum = 0; 
    foreach (object o in a) 
    { 

     if (o is MemoryStream) 
     { 
      var m = o as MemoryStream; 
      sum += (int)m.Length; 
     } 
    } 
    sw.Stop(); 
    Console.WriteLine("As: {0} : {1}", sum, 
         (long)sw.ElapsedMilliseconds); 
} 

static void UsingCast(object[] values) 
{ 
    object[] a = values.ToArray(); 

    Stopwatch sw = Stopwatch.StartNew(); 
    int sum = 0; 
    foreach (object o in a) 
    { 
     if (o is MemoryStream) 
     { 
      var m = (MemoryStream)o; 
      sum += (int)m.Length; 
     } 
    } 
    sw.Stop(); 
    Console.WriteLine("Cast: {0} : {1}", sum, 
         (long)sw.ElapsedMilliseconds); 
} 

... Sorties:

Cast: 0 : 282 
As: 0 : 282 

Maintenant, ils ont les mêmes résultats, merci Remus!

En cours d'exécution, Cast et As indépendamment, ils donnent également le même résultat (c'est-à-dire 282). Maintenant, quant à pourquoi ils deviennent plus rapides (de 322 à 282 millisecondes) quand ils sont remis leur propre copie de tableau, je ne peux rien en tirer :-) C'est entièrement une autre histoire

+0

Vous savez que le moyen le plus rapide est de ne pas vérifier 'is', d'utiliser l'opérateur' as' et de tester le résultat pour '== null'. –

+0

Je ne demande pas comment rendre le code plus rapide. Je demande comment faire un bon benchmarking. Et j'ai un soupçon que quelqu'un va suggérer d'utiliser 'as' et tester pour' == null' (bien quelqu'un a), c'est triste à dire, cette approche est plus lente que les deux des deux codes ci-dessus –

Répondre

1

Si vous Si vous voulez sortir de l'image le cache L2 et le TLB manque alors appelez simplement le second test sur un MemoryStream différent de la même taille.