Cómo invalidar caché cuando la evaluación comparativa?
-
30-09-2019 - |
Pregunta
Tengo este código, que cuando se cambia el orden de UsingAs y UsingCast, su rendimiento también permutas.
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);
}
}
Salidas:
As: 0 : 322
Cast: 0 : 281
Al hacer esto ...
UsingCast(values);
UsingAs(values);
... Resultados para esto:
Cast: 0 : 322
As: 0 : 281
Al hacer esto solo ...
UsingAs(values);
... Resultados para esto:
As: 0 : 322
Al hacer esto:
UsingCast(values);
... Resultados para esto:
Cast: 0 : 322
Además de correr de forma independiente, la forma de invalidate la caché por lo que el segundo código siendo punto de referencia no recibirán la memoria caché del primer código?
La evaluación comparativa a un lado, le encantó el hecho de que los procesadores modernos hacen caché de magia: -)
[EDIT]
Como aconsejó a probar este código más rápido (supuestamente) ...
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);
}
... El resultado es el siguiente:
As and null test: 0 : 342
Más lento que los dos códigos anteriormente
[EDIT]:
Como aconsejó a mano cada rutina de su propia copia ...
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);
}
... Salidas:
Cast: 0 : 282
As: 0 : 282
Ahora tienen los mismos resultados, gracias Remus!
Funcionamiento moldeada y lo más independientemente, sino que también dan el mismo resultado (es decir. 282). Ahora, en cuanto a por qué se vuelven rápido (de 322 a 282 milisegundos) cuando son entregados a su propia copia de la matriz, no puede hacer nada de él :-) Eso es totalmente otra historia
Solución
Si usted quiere tomar fuera de la imagen de la memoria caché L2 y la TLB entonces simplemente llamar a la segunda prueba en un MemoryStream diferente del mismo tamaño.