Come per invalidare la cache quando l'analisi comparativa?
-
30-09-2019 - |
Domanda
Ho questo codice, che quando scambiando l'ordine di UsingAs e UsingCast, le loro prestazioni anche swap.
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);
}
}
Uscite:
As: 0 : 322
Cast: 0 : 281
Nel fare questo ...
UsingCast(values);
UsingAs(values);
... Risultati a questo:
Cast: 0 : 322
As: 0 : 281
Nel fare proprio questo ...
UsingAs(values);
... Risultati a questo:
As: 0 : 322
Nel fare proprio questo:
UsingCast(values);
... Risultati a questo:
Cast: 0 : 322
Oltre a correre in modo indipendente, come invalidate la cache in modo che il secondo codice in fase di benchmark non riceveranno la memoria cache di primo codice?
L'analisi comparativa a parte, mi è piaciuto molto il fatto che i processori moderni fanno caching magica: -)
[EDIT]
Per quanto consigliato di provare questo codice più veloce (presumibilmente) ...
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);
}
... Il risultato è questo:
As and null test: 0 : 342
Più lento di due codici sopra
[EDIT]:
Per quanto consigliato a portata di mano ogni routine la propria 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);
}
... Uscite:
Cast: 0 : 282
As: 0 : 282
Ora hanno gli stessi risultati, grazie Remo!
Cast corsa e As indipendentemente, hanno anche producono lo stesso risultato (cioè. 282). Ora, per quanto riguarda il motivo per cui diventano più veloce (da 322 fino a 282 millisecondi) quando vengono consegnati la propria copia di array, che non può fare nulla fuori di esso :-) Questo è tutto un altro discorso
Soluzione
Se si vuole prendere fuori dal quadro della cache L2 e il TLB poi semplicemente chiamare il secondo test su una diversa MemoryStream della stessa dimensione.