Comment invalider le cache lors de l'analyse comparative?
-
30-09-2019 - |
Question
Je le code, que lorsque la permutation de l'ordre de UsingAs et UsingCast, leurs performances aussi des swaps.
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 à ceci:
Cast: 0 : 322
As: 0 : 281
Quand vous faites tout cela ...
UsingAs(values);
... Résultats à ceci:
As: 0 : 322
Quand vous faites ceci:
UsingCast(values);
... Résultats à ceci:
Cast: 0 : 322
En plus de les exécuter de façon indépendante, comment invalidate le cache de sorte que le second code étant étalonnée ne recevront pas la mémoire cache du premier code?
Analyse comparative de 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
lent que les deux codes ci-dessus
[EDIT]:
Comme conseillé de remettre chaque routine de 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!
Ensemble de course et de manière aussi autonome, ils donnent aussi le même résultat (à savoir. 282). Maintenant, pour pourquoi ils deviennent plus rapide (de 322 jusqu'à 282 millisecondes) quand ils sont remis leur propre copie du tableau, je ne peux rien faire sortir :-) C'est tout à fait une autre histoire
La solution
Si vous voulez sortir de l'image du cache L2 et le TLB alors il suffit d'appeler le second test sur un MemoryStream différent de la même taille.