Question

Bougez sur Paramètres C # ont des implications sur les performances que je devrais savoir? (Comme exceptions)

Je veux dire, est-il une bonne idée d'avoir une méthode avec un paramètre out dans une boucle qui se déroulera deux millions de fois par seconde?

Je sais qu'il est laid, mais je l'utilise de la même façon que Int32.TryParse les utilise -. Retourner un bool pour dire si une validation a réussi et ayant un paramètre out contenant des données supplémentaires si elle a réussi

Était-ce utile?

La solution

Je doute que vous trouverez une pénalité de performance significative à l'aide d'un paramètre out. Vous devez obtenir de l'information à l'appelant tant bien que mal - out est juste une autre façon de le faire. Vous trouverez peut-être il y a certains pénalité si vous utilisez le paramètre de façon extensive dans la méthode, car cela pourrait bien signifier un niveau de redirection supplémentaire pour chaque accès. Cependant, je ne m'y attendais pas à être significatif. Comme d'habitude, écrire le code plus lisible et tester si la performance est déjà assez bon avant d'essayer d'optimiser davantage.

EDIT: Le reste de ce côté est, de façon efficace. Il est seulement vraiment pertinent pour les types de valeur, ce qui devrait généralement être évités en tout cas:)

Je suis en désaccord avec l'affirmation de Konrad sur les « valeurs de retour pour tous les types> 32 bits sont traités similaires ou identiques à des arguments sur le niveau de la machine de toute façon » cependant. Voici une application peu de test:

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

Résultats:

Using return value: 11316
Using out parameter: 7461

En fait à l'aide d'un paramètre sur nous écrivons les données directement à la destination finale, plutôt que de l'écrire au cadre de la pile de la petite méthode, puis le copier de nouveau dans le cadre de la pile de la méthode principale.

Sentez-vous libre de critiquer l'application de référence si - j'avoir quelque chose manqué

Autres conseils

Pas un problème de performance, mais quelque chose qui est venu plus tôt - vous ne pouvez pas les utiliser avec la variance dans C # 4.0 .

Personnellement, je tendance à utiliser les paramètres de out un juste montant dans mon privée code (dans une classe, ayant une méthode qui renvoie des valeurs multiples sans utiliser un type distinct) - mais je tends à éviter les sur l'API publique, sauf pour le motif de bool Try{Something}(out result).

Il n'y a pas de conséquences sur les performances. out est fondamentalement la même que tout ancien passage d'arguments, d'un point de vue technique. Bien que cela puisse paraître plausible que d'énormes amounds de données sont copiées (par exemple pour les grandes struct), c'est en fait la même chose que pour les valeurs de retour.

En fait, le retour des valeurs pour tous les types> 32 bits sont traités similaires à out arguments sur le niveau de la machine de toute façon.

S'il vous plaît noter que la dernière déclaration ne suggère pas que le retour d'une valeur == paramètre out dans .NET. L'indice de référence Jon montre que ce qui est évidemment (et malheureusement) pas le cas. En fait, pour la rendre identique, optimisation du nom de valeur de retour est utilisé dans les compilateurs C. Quelque chose de semblable pourrait être fait dans les versions futures du JIT pour améliorer les performances de retour de grandes structures (cependant, étant donné que les grandes structures sont assez rares dans .NET, cela pourrait être une optimisation inutile).

Cependant , (et avec ma connaissance très limitée de l'ensemble x86), les objets de retour de la fonction des appels implique généralement allouer suffisamment d'espace sur le site d'appel, poussant l'adresse sur la pile et le remplir en copiant la valeur de retour en elle. Ceci est essentiellement le même que out ne, que l'omission d'une copie temporaire inutile de la valeur depuis l'emplacement de mémoire cible est directement accessible.

La raison principale pour éviter des paramètres est la lisibilité du code, plutôt que la performance.

Pour les types de valeur il n'y a pas de différence réelle de toute façon (ils copient toujours) et pour les types de référence, il est essentiellement la même que celle qui passe par ref.

Neuf fois sur dix, vous êtes mieux de créer votre propre classe d'enregistrement muet, plutôt que d'utiliser un paramètre out -. C'est plus simple à lire et à comprendre quand vous revenez au code plus tard

Out paramètres sont passés par ref. Ainsi, seul un pointeur passé sur la pile.

Si votre type de valeur est grande, il y a moins de copie, mais vous devez déréférencer le pointeur sur chaque utilisation variable.

En utilisant un paramètre out ne fait pas mal des performances. Un paramètre de sortie est fondamentalement un paramètre de référence, de sorte que à la fois l'appelant et le point appelé de la même partie de la mémoire.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top