Frage

Do aus Parameter in C # haben keine Auswirkungen auf die Leistung sollte ich über? (Wie Ausnahmen)

Ich meine, ist es eine gute Idee, ein Verfahren mit einem out Parameter in einer Schleife zu haben, die ein paar Millionen Mal pro Sekunde ausgeführt werden?

Ich weiß, es ist hässlich, aber ich es auf die gleiche Weise wie Int32.TryParse verwende ist sie mit -. Eine bool Rückkehr zu sagen, ob einige Validierung erfolgreich war und mit einem out Parameter einige zusätzliche Daten enthalten, wenn es erfolgreich war

War es hilfreich?

Lösung

Ich bezweifle, dass Sie mit einem out Parameter eine signifikante Leistungseinbuße finden. Du hast irgendwie oder andere Informationen zurück an den Anrufer zu bekommen - out ist nur eine andere Art und Weise tun. Sie können feststellen, gibt es einig Strafe, wenn Sie die Out-Parameter ausführlich innerhalb der Methode verwenden, da es auch eine zusätzliche Ebene der Umleitung für jeden Zugriff bedeuten kann. Allerdings würde ich nicht erwarten, dass es von Bedeutung sein. Wie normal, schreiben die meisten lesbaren Code und Test, ob die Leistung schon gut genug ist, bevor weiter zu optimieren versuchen.

EDIT: Der Rest ist dies eine Seite, effektiv. Es ist nur wirklich relevant für große Werttypen, die in der Regel ohnehin vermieden werden sollten:)

ich mit Konrad Behauptung nicht einig über „Rückgabewerte für alle Typen> 32 Bit sind ohnehin ähnlich oder identisch aus Argumenten auf der Maschinenebene behandelt“ though. Hier ist ein kleiner Test-App:

using System;
using System.Diagnostics;
using System.Runtime.CompilerServices;

struct BigStruct
{
    public Guid guid1, guid2, guid3, guid4;
    public decimal dec1, dec2, dec3, dec4;
}

class Test
{
    const int Iterations = 100000000;

    static void Main()
    {
        decimal total = 0m;
        // JIT first
        ReturnValue();
        BigStruct tmp;
        OutParameter(out tmp);

        Stopwatch sw = Stopwatch.StartNew();
        for (int i=0; i < Iterations; i++)
        {
            BigStruct bs = ReturnValue();
            total += bs.dec1;
        }
        sw.Stop();
        Console.WriteLine("Using return value: {0}",
                          sw.ElapsedMilliseconds);

        sw = Stopwatch.StartNew();
        for (int i=0; i < Iterations; i++)
        {
            BigStruct bs;
            OutParameter(out bs);
            total += bs.dec1;
        }
        Console.WriteLine("Using out parameter: {0}",
                          sw.ElapsedMilliseconds);
    }

    [MethodImpl(MethodImplOptions.NoInlining)]
    public static BigStruct ReturnValue()
    {
        return new BigStruct();
    }

    [MethodImpl(MethodImplOptions.NoInlining)]
    public static void OutParameter(out BigStruct x)
    {
        x = new BigStruct();
    }
}

Ergebnisse:

Using return value: 11316
Using out parameter: 7461

Im Grunde genommen durch einen Out-Parameter verwenden wir die Daten direkt an das endgültigen Ziel schreiben, anstatt sie zu der kleinen Methode der Stack-Frame zu schreiben und es dann Kopieren wieder in die Stack-Frame der Main-Methode.

Sie können ferner auch wenn die Benchmark App zu kritisieren - ich kann etwas verpasst haben

Andere Tipps

Nicht ein Performance-Problem, sondern etwas, das früher kam - man sie nicht mit der Varianz in C # 4.0 verwenden kann.

Persönlich neige ich out Parameter eine ganze Menge in meinem privat Code (dh innerhalb einer Klasse, eine Methode, die mehrere Werte zurückgibt, ohne eine separate Art verwendet wird) verwenden - aber ich neige zu vermeiden sie auf der öffentlichen API, mit Ausnahme des bool Try{Something}(out result) Muster.

Es gibt keine Auswirkungen auf die Leistung. out ist im Grunde das gleiche wie jedes alte Argument nebenbei, aus technischer Sicht. Während es plausibel klingen mag, dass riesige amounds von Daten kopiert werden (zum Beispiel für große Strukturen), das ist eigentlich die gleiche wie für die Rückgabewerte.

In der Tat, Rückgabewerte für alle Typen> 32 Bit ähnlich gehandhabt werden Argumente auf der Seite Maschine Ebene out trotzdem.

Bitte beachten Sie, dass die letzte Anweisung bedeutet nicht, dass ein Wert == out Parameter in .NET zurück. Jon Benchmark zeigt, dass dies offensichtlich (und leider) nicht der Fall. In der Tat, es gleich zu machen, benannte Rückgabewert Optimierung in C ++ Kompilierer eingesetzt. Etwas Ähnliches könnte möglicherweise in zukünftigen Versionen des JIT getan wird zur Verbesserung der Leistung von großen Strukturen zurückkehrt (da jedoch große Strukturen in .NET recht selten sind, könnte dies eine unnötige Optimierung sein).

Jedoch , (und mit meinem sehr begrenzten Wissen über x86-Assembler), Objekte aus der Funktion zurückkehrt ruft bringt im Allgemeinen ausreichend Platzes an der Aufrufstelle Zuweisung auf dem Stapel die Adresse drücken und füllte sie durch Kopieren der Rückgabewert hinein. Dies ist im Grunde das gleiche, dass out der Fall ist, nur eine unnötige temporäre Kopie des Wertes weggelassen, da kann die Zielspeicherstelle direkt zugegriffen werden.

Der Hauptgrund für die Parameter heraus vermeiden, um die Lesbarkeit des Codes ist, anstatt Leistung.

Für Werttypen gibt es keinen wirklichen Unterschied sowieso (sie kopieren immer) und für Referenztypen ist es im Grunde das gleiche wie durch ref übergeben.

In neun von zehn du bist besser dran Ihre eigene stumme Rekord-Klasse erstellen, anstatt mit einem Out-Parametern -. Dies ist einfacher zu lesen und zu verstehen, wenn Sie auf den Code später zurück

Out-Parameter werden durch ref übergeben. Also nur ein Zeiger auf dem Stack übergeben.

Wenn Ihr Wert Typ, der groß ist, gibt es weniger zu kopieren, aber dann haben Sie auf den Zeiger dereferenzieren auf jede Variable verwenden.

out-Parameter verwenden die Leistung nicht verletzt. Ein Out-Parameter ist im Grunde ein Referenzparameter, so dass sowohl der Anrufer und der Angerufene auf das gleiche Stück Erinnerung.

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