1

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

それらを個別に実行する以外に、キャッシュを無効にして、ベンチマークされている2番目のコードが最初のコードのキャッシュされたメモリを受信しないようにする方法は?

ベンチマークはさておき、最新のプロセッサがこのキャッシング マジックを行うという事実が気に入りました :-)

[編集]

このより高速なコードを試すようにアドバイスされているように(おそらく)...

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

上記の 2 つのコードより遅い

[編集]:

各ルーチンに独自のコピーを渡すことをお勧めします...

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 に感謝します!

Cast と As を個別に実行しても、同じ結果 (つまり 282) が得られます。さて、配列の独自のコピーを渡されたときになぜ速くなったのか (322 ミリ秒から 282 ミリ秒まで) については、私はそれから何も理解できません :-) それはまったく別の話です

4

1 に答える 1

1

写真からL2キャッシュを取り出して、TLBが失敗した場合は、同じサイズの別のMemoryStreamで2番目のテストを呼び出すだけです。

于 2010-04-21T03:17:48.520 に答える