Riesiger Leistungsunterschied (26x schneller) beim Kompilieren für 32- und 64-Bit

Ich habe versucht, den Unterschied zwischen der Verwendung eines @ zu messefor und einforeach beim Zugriff auf Listen mit Werttypen und Referenztypen.

Ich habe die folgende Klasse für die Profilerstellung verwendet.

public static class Benchmarker
{
    public static void Profile(string description, int iterations, Action func)
    {
        Console.Write(description);

        // Warm up
        func();

        Stopwatch watch = new Stopwatch();

        // Clean up
        GC.Collect();
        GC.WaitForPendingFinalizers();
        GC.Collect();

        watch.Start();
        for (int i = 0; i < iterations; i++)
        {
            func();
        }
        watch.Stop();

        Console.WriteLine(" average time: {0} ms", watch.Elapsed.TotalMilliseconds / iterations);
    }
}

Ich benutztedouble für meinen Werttyp. Und ich habe diese 'gefälschte Klasse' erstellt, um Referenztypen zu testen:

class DoubleWrapper
{
    public double Value { get; set; }

    public DoubleWrapper(double value)
    {
        Value = value;
    }
}

Schließlich habe ich diesen Code ausgeführt und die Zeitunterschiede verglichen.

static void Main(string[] args)
{
    int size = 1000000;
    int iterationCount = 100;

    var valueList = new List<double>(size);
    for (int i = 0; i < size; i++) 
        valueList.Add(i);

    var refList = new List<DoubleWrapper>(size);
    for (int i = 0; i < size; i++) 
        refList.Add(new DoubleWrapper(i));

    double dummy;

    Benchmarker.Profile("valueList for: ", iterationCount, () =>
    {
        double result = 0;
        for (int i = 0; i < valueList.Count; i++)
        {
             unchecked
             {
                 var temp = valueList[i];
                 result *= temp;
                 result += temp;
                 result /= temp;
                 result -= temp;
             }
        }
        dummy = result;
    });

    Benchmarker.Profile("valueList foreach: ", iterationCount, () =>
    {
        double result = 0;
        foreach (var v in valueList)
        {
            var temp = v;
            result *= temp;
            result += temp;
            result /= temp;
            result -= temp;
        }
        dummy = result;
    });

    Benchmarker.Profile("refList for: ", iterationCount, () =>
    {
        double result = 0;
        for (int i = 0; i < refList.Count; i++)
        {
            unchecked
            {
                var temp = refList[i].Value;
                result *= temp;
                result += temp;
                result /= temp;
                result -= temp;
            }
        }
        dummy = result;
    });

    Benchmarker.Profile("refList foreach: ", iterationCount, () =>
    {
        double result = 0;
        foreach (var v in refList)
        {
            unchecked
            {
                var temp = v.Value;
                result *= temp;
                result += temp;
                result /= temp;
                result -= temp;
            }
        }

        dummy = result;
    });

    SafeExit();
}

Ich wählteRelease undAny CPU options, ließ das Programm laufen und bekam folgende Zeiten:

valueList for:  average time: 483,967938 ms
valueList foreach:  average time: 477,873079 ms
refList for:  average time: 490,524197 ms
refList foreach:  average time: 485,659557 ms
Done!

Dann habe ich die Optionen Release und x64 ausgewählt, das Programm ausgeführt und die folgenden Zeiten erhalten:

valueList for:  average time: 16,720209 ms
valueList foreach:  average time: 15,953483 ms
refList for:  average time: 19,381077 ms
refList foreach:  average time: 18,636781 ms
Done!

Warum ist die x64-Bit-Version so viel schneller? Ich habe einen Unterschied erwartet, aber nichts so Großes.

Ich habe keinen Zugriff auf andere Computer. Könnten Sie dies bitte auf Ihren Rechnern ausführen und mir die Ergebnisse mitteilen? Ich verwende Visual Studio 2015 und habe ein IntelCore i7 930.

Hier ist dieSafeExit() -Methode, damit Sie selbst kompilieren / ausführen können:

private static void SafeExit()
{
    Console.WriteLine("Done!");
    Console.ReadLine();
    System.Environment.Exit(1);
}

Wie angefordert mitdouble? anstelle von meinemDoubleWrapper:

Jede CPU

valueList for:  average time: 482,98116 ms
valueList foreach:  average time: 478,837701 ms
refList for:  average time: 491,075915 ms
refList foreach:  average time: 483,206072 ms
Done!

x64

valueList for:  average time: 16,393947 ms
valueList foreach:  average time: 15,87007 ms
refList for:  average time: 18,267736 ms
refList foreach:  average time: 16,496038 ms
Done!

Last but not least: Erstellen einesx86it dem @ -Profil erhalte ich fast die gleichen Ergebnisse wie mitAny CPU.

Antworten auf die Frage(8)

Ihre Antwort auf die Frage