Вопрос

У меня есть этот код, что при замене заказа на использование и с использованием их производительность также сводится.

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

Теперь у них такие же результаты, спасибо Remus!

Запуск литья и как независимо, они также дают один и тот же результат (т.е. 282). Теперь, как и за то, почему они становятся Быстрее (от 322 до 282 миллисекунд), когда они передают свою собственную копию массива, я не могу ничего сделать из этого :-) Это совершенно другая история

Это было полезно?

Решение

Если вы хотите вывести из картинки, кэш L2 и промахи TLB просто просто позвоните второму тесту на другой память одинакового размера.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top