Как сделать недействительным кеш при тестировании?
У меня есть этот код, что при переключении порядка использования As и UsingCast их производительность также меняется.
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);
}
}
Выходы:
As: 0 : 322
Cast: 0 : 281
Делая это...
UsingCast(values);
UsingAs(values);
... Результаты к этому:
Cast: 0 : 322
As: 0 : 281
Делая только это...
UsingAs(values);
... Результаты к этому:
As: 0 : 322
Делая только это:
UsingCast(values);
... Результаты к этому:
Cast: 0 : 322
Помимо их независимого запуска, как сделать кеш недействительным, чтобы второй тестируемый код не получал кэшированную память первого кода?
Помимо тестов, просто понравилось то, что современные процессоры делают это волшебство кеширования:-)
[РЕДАКТИРОВАТЬ]
Как советуют попробовать этот более быстрый код (предположительно)...
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);
}
... Результат таков:
As and null test: 0 : 342
Медленнее, чем два кода выше
[РЕДАКТИРОВАТЬ]:
Как посоветовали передать каждой рутине свою копию...
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);
}
... Выходы:
Cast: 0 : 282
As: 0 : 282
Теперь у них одинаковые результаты, спасибо Ремус!
Запуск Cast и As независимо, они также дают тот же результат (то есть 282). Теперь, что касается того, почему они становятся быстрее (с 322 до 282 миллисекунд), когда им вручают свою собственную копию массива, я ничего не могу из этого сделать:-) Это совсем другая история
1 ответ
Если вы хотите исключить кэш L2 и TLB, то просто вызовите второй тест для другого MemoryStream того же размера.