У меня есть этот код, что при замене порядка UsingAs и 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
Помимо запуская их независимо друг от друга , как аннулировать кэш, так что вторая треска e, сравниваемый по критериям, не получит кэшированную память первого кода?
Бенчмаркинг в сторону, просто любил тот факт, что современные процессоры делают это кэширование магии :-)
[EDIT]
Как советуют попробовать это более быстрый код (предположительно) ...
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
Медленнее, чем двумя кодами выше
[EDIT]:
Как советуют сдавать каждый рутинную свою собственную копию ...
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 миллисекунд), когда им вручают свою собственную копию массива, я ничего не могу сделать из этого :-) Это совсем другая история.
Вы знаете, что самый быстрый способ - не проверять 'is', использовать оператор' as' и проверить результат для '== null'. –
Я не спрашиваю, как сделать код быстрее. Я спрашиваю, как сделать правильный бенчмаркинг. И у меня есть подозрение, что кто-то предложит использовать 'as' и тест для' == null' (ну кто-нибудь есть), к сожалению, этот подход медленнее, чем оба этих двух кода выше –