Domanda

Ho questo codice, che quando scambiando l'ordine di UsingAs e UsingCast, le loro prestazioni anche swap.

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


}

Uscite:

As: 0 : 322
Cast: 0 : 281

Nel fare questo ...

UsingCast(values);
UsingAs(values);

... Risultati a questo:

Cast: 0 : 322
As: 0 : 281

Nel fare proprio questo ...

UsingAs(values);

... Risultati a questo:

As: 0 : 322

Nel fare proprio questo:

UsingCast(values);

... Risultati a questo:

Cast: 0 : 322

Oltre a correre in modo indipendente, come invalidate la cache in modo che il secondo codice in fase di benchmark non riceveranno la memoria cache di primo codice?

L'analisi comparativa a parte, mi è piaciuto molto il fatto che i processori moderni fanno caching magica: -)

[EDIT]

Per quanto consigliato di provare questo codice più veloce (presumibilmente) ...

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

... Il risultato è questo:

As and null test: 0 : 342

Più lento di due codici sopra

[EDIT]:

Per quanto consigliato a portata di mano ogni routine la propria copia ...

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

... Uscite:

Cast: 0 : 282
As: 0 : 282

Ora hanno gli stessi risultati, grazie Remo!

Cast corsa e As indipendentemente, hanno anche producono lo stesso risultato (cioè. 282). Ora, per quanto riguarda il motivo per cui diventano più veloce (da 322 fino a 282 millisecondi) quando vengono consegnati la propria copia di array, che non può fare nulla fuori di esso :-) Questo è tutto un altro discorso

È stato utile?

Soluzione

Se si vuole prendere fuori dal quadro della cache L2 e il TLB poi semplicemente chiamare il secondo test su una diversa MemoryStream della stessa dimensione.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top