Frage

Ich habe diesen Code, dass, wenn Vertauschen der Reihenfolge der UsingAs und UsingCast, ihre Leistung auch Swaps.

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);
    }


}

Ausgänge:

As: 0 : 322
Cast: 0 : 281

Wenn dies zu tun ...

UsingCast(values);
UsingAs(values);

... Such folgt aus:

Cast: 0 : 322
As: 0 : 281

Wenn gerade dabei diesen ...

UsingAs(values);

... Such folgt aus:

As: 0 : 322

Wenn gerade dabei diese:

UsingCast(values);

... Such folgt aus:

Cast: 0 : 322

Abgesehen von ihnen unabhängig läuft, wie man Invalidier der Cache so der zweite Code gebenchmarkt wird nicht die im Cache gespeicherte Erinnerung an ersten Code erhalten?

Benchmarking beiseite, liebte die Tatsache, dass moderne Prozessoren diese Caching Magie tun: -)

[EDIT]

Wie empfohlen, diesen schnelleren Code zu versuchen, (angeblich) ...

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);
}

... Das Ergebnis ist dieses:

As and null test: 0 : 342

Langsamer als die beiden Codes oben

[EDIT]:

Wie geraten jede Routine ihre eigene Kopie zur Hand ...

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);
}

... Ausgang:

Cast: 0 : 282
As: 0 : 282

Jetzt haben sie die gleichen Ergebnisse, dank Remus!

Running Cast und als unabhängig ergeben sie auch das gleiche Ergebnis (d. 282). Nun, wie, warum sie werden schneller (von 322 bis 282 Millisekunden), wenn sie ihre eigene Kopie des Arrays übergeben werden, kann ich nichts draus machen kann :-) Das ist eine ganz andere Geschichte

War es hilfreich?

Lösung

Wenn Sie im Bild-Cache die L2 herauszunehmen und die TLB-Fehler dann rufen Sie einfach den zweiten Test auf einem anderen Memorystream von der gleichen Größe.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top