Domanda

Fare fuori parametri C# qualsiasi implicazioni in termini di prestazioni dovrei sapere?(Come eccezioni)

Voglio dire, è una buona idea avere un metodo con un out parametro in un ciclo che verrà eseguito un paio di milioni di volte al secondo?

So che è brutto ma io sto usando lo stesso modo come Int32.TryParse è il loro utilizzo - la restituzione di un bool per verificare se la convalida è successo e di avere un out parametro contiene alcuni dati aggiuntivi se è stato un successo.

È stato utile?

Soluzione

Dubito che potrai trovare qualsiasi riduzione significativa delle prestazioni di utilizzo di un out parametro.Hai avuto modo di ottenere informazioni al chiamante un modo o nell'altro - out è solo un modo diverso di farlo.Si possono trovare c'è alcuni penalità se si utilizza il parametro ampiamente all'interno del metodo, come si può ben dire un ulteriore livello di reindirizzamento per ogni accesso.Tuttavia, non mi aspetto di essere significativo.Come normale, scrivere il più leggibile il codice e verificare se le prestazioni è già abbastanza buono prima di cercare di ottimizzare ulteriormente.

EDIT:Il resto di questo è che un a parte, in modo efficace.È davvero rilevante solo per i grandi tipi di valore, che di solito dovrebbe essere evitato in ogni caso :)

Io non sono d'accordo con Konrad affermazione sui "valori di ritorno per tutti i tipi > 32 bit vengono gestiti simili o identici ad argomenti sulla macchina, il livello è comunque" anche se.Ecco una piccola applicazione di prova:

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

Risultati:

Using return value: 11316
Using out parameter: 7461

Fondamentalmente utilizzando un parametro out stiamo scrivendo i dati direttamente alla destinazione finale, piuttosto che scrivere per il piccolo metodo stack frame e poi ricopiare questo metodo Main stack frame.

Sentitevi liberi di criticare il punto di riferimento app anche se - mi sono persa qualcosa!

Altri suggerimenti

Non è un problema di prestazioni, ma di qualcosa che è venuto prima - non si possono usare con la varianza in C# 4.0.

Personalmente, tendo ad utilizzare out i parametri di una discreta quantità nel mio privato codice (es.all'interno di una classe, avere un metodo che restituisce valori multipli senza l'utilizzo di un tipo separato) - ma io tendo a evitare che il pubblico di API, fatta eccezione per il bool Try{Something}(out result) modello.

Non ci sono implicazioni in termini di prestazioni. out è fondamentalmente lo stesso come qualsiasi vecchio argomento passando, da un punto di vista tecnico.Mentre potrebbe sembrare plausibile che enorme amounds di dati vengono copiati (ad es.per le grandi strutture), questo è in realtà lo stesso per i valori di ritorno.

Infatti, i valori di ritorno per tutti i tipi > 32 bit vengono gestiti simile a out argomenti a livello di macchina comunque.

Siete pregati di notare che l'ultima istruzione non suggeriscono che la restituzione di un valore di == out parametro .NET.Jon benchmark dimostra che questo non è ovviamente (e purtroppo) non è il caso.Infatti, per renderlo identico, nome valore di ritorno di ottimizzazione è impiegato in compilatori C++.Qualcosa di simile potrebbe potenzialmente essere fatto in future versioni del JIT per migliorare le prestazioni di restituzione di strutture di grandi dimensioni (tuttavia, poiché le grandi strutture sono abbastanza rare in .NET, questo potrebbe essere un inutile ottimizzazione).

Tuttavia, (e con la mia limitata conoscenza di assembler x86), restituzione di oggetti di chiamate di funzione comporta l'allocazione di spazio sufficiente al sito di chiamata, spingendo l'indirizzo nello stack e il riempimento copiando il valore di ritorno in esso.Questo è fondamentalmente lo stesso che out non solo l'omissione di un inutile copia temporanea del valore, in quanto il percorso della memoria di destinazione, è possibile accedere direttamente.

La principale ragione per evitare di parametri è la leggibilità del codice, piuttosto che le prestazioni.

Per i tipi di valore non c'è una vera differenza comunque (sempre copia) e per i tipi di riferimento è sostanzialmente la stessa che passa dal rif.

Nove volte su dieci è meglio creare il proprio scemo della classe record, piuttosto che utilizzando un parametro out - questo è più semplice da leggere e capire quando si torna al codice in un secondo momento.

Parametri vengono passati da ref.Pertanto, solo un puntatore passato in pila.

Se il vostro tipo di valore è grande, c'è meno di copia, ma poi devi dereferenziare il puntatore su ogni variabile.

Utilizzando un parametro non compromettere le prestazioni.Un parametro è fondamentalmente un parametro di riferimento, in modo che sia il chiamante che il chiamato punto per lo stesso pezzo di memoria.

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