82 votes

Terrain vs Propriété. Optimisation des performances

Veuillez noter que cette question a trait à la performance uniquement. Permet de sauter des lignes directrices de conception, de la philosophie, de la compatibilité, de la portabilité et de tout ce qui n'est pas liée à la performance pure. Je vous remercie.

Maintenant à la question. J'ai toujours supposé que parce que le C# getters/setters sont vraiment des méthodes dans le déguisement de lecture publique de champ doit être plus rapide que d'appeler un getter.

Pour m'en assurer, j'ai fait un test (le code ci-dessous). Toutefois, ce test ne produit que des résultats attendus (c'est à dire les champs sont plus rapides que les méthodes de lecture à 34%) si vous l'exécutez à partir à l'intérieur de Visual Studio.

Une fois que vous l'exécutez à partir de la ligne de commande, il montre à peu près le même timing...

La seule explication pourrait être que le CLR ne supplémentaires d'optimisation (corrigez-moi si je me trompe ici).

Je ne crois pas que dans la vraie demande où ces propriétés sont utilisées dans beaucoup plus évoluée de la manière dont ils vont être optimisées de la même façon.

Merci de m'aider à prouver ou à réfuter l'idée que dans la vraie vie, les propriétés sont plus lents que les champs.

La question est de savoir comment dois - je modifier les classes de test pour faire le CLR changement de comportement de sorte que le champ public outperfroms les getters. OU me montrer que toute propriété sans logique interne effectuera le même comme un champ (au moins sur le getter)

EDIT: je ne parle que de Version version x64.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace PropertyVsField
{
    class Program
    {
        static int LEN = 20000000;
        static void Main(string[] args)
        {
            List<A> a = new List<A>(LEN);
            List<B> b = new List<B>(LEN);

            Random r = new Random(DateTime.Now.Millisecond);

            for (int i = 0; i < LEN; i++)
            {
                double p = r.NextDouble();
                a.Add(new A() { P = p });
                b.Add(new B() { P = p });
            }

            Stopwatch sw = new Stopwatch();

            double d = 0.0;

            sw.Restart();
            for (int i = 0; i < LEN; i++)
            {
                d += a[i].P;
            }

            sw.Stop();

            Console.WriteLine("auto getter. {0}. {1}.", sw.ElapsedTicks, d);

            sw.Restart();
            for (int i = 0; i < LEN; i++)
            {
                d += b[i].P;
            }

            sw.Stop();

            Console.WriteLine("      field. {0}. {1}.", sw.ElapsedTicks, d);

            Console.ReadLine();
        }
    }

    class A
    {
        public double P { get; set; }
    }
    class B
    {
        public double P;
    }
}

66voto

Heinzi Points 66519

Comme d'autres l'ont déjà mentionné, les accesseurs sont inline.

Si vous voulez éviter l'in-lining, vous avez pour

  • remplacer le système automatique de propriétés avec les manuels:

    class A 
    {
        private double p;
        public double P
        {
            get { return p; }
            set { p = value; }
        }
    } 
    
  • et de dire au compilateur de ne pas inline de la lecture (ou les deux, si vous en avez envie):

            [MethodImpl(MethodImplOptions.NoInlining)]
            get { return p; }
    

Notez que le premier changement ne permet pas de faire une différence dans la performance, tandis que le deuxième changement montre clairement un appel de méthode généraux:

Manuel de propriétés:

auto getter. 519005. 10000971,0237547.
      field. 514235. 20001942,0475098.

Pas d'alignement de la lecture:

auto getter. 785997. 10000476,0385552.
      field. 531552. 20000952,077111.

29voto

JamieSee Points 6010

Regardez les Propriétés vs Champs – Pourquoi est-il important? (Jonathan Aneja) article du blog de l'un des VB membres de l'équipe sur MSDN. Il décrit la propriété par rapport à des champs argument et explique aussi trivial propriétés comme suit:

Un argument que j'ai entendu pour l'utilisation des champs de plus de propriétés, c'est que "les champs sont plus rapides", mais pour trivial propriétés qui ne l'est pas réellement vrai, comme le CLR En Juste-à-Temps (JIT) compilateur inline l' l'accès à la propriété et de générer du code qui est aussi efficace que l'accès à un domaine directement en.

12voto

Guvante Points 10338

L'équipe en ligne des méthode (et pas seulement un getter) interne métriques de déterminer sera plus rapide inline. Étant donné que le standard de la propriété est - return _Property; il sera incorporé dans tous les cas.

La raison que vous voyez un comportement différent, c'est que dans le mode de Débogage avec un débogueur, l'équipe est très handicapés, pour s'assurer que tous les emplacements de pile correspondent à ce que vous attendez du code.

Vous êtes également oublier la règle numéro un de la performance, les essais beats pensée. Par exemple, même si le tri rapide est asymptotiquement plus rapide que le tri par insertion, le tri par insertion est effectivement plus rapide pour les très petites entrées.

8voto

TomTom Points 35574

La seule explication pourrait être que le CLR ne supplémentaires d'optimisation (correrct moi si je me trompe ici).

Oui, il est appelé inline. Il est fait dans le compilateur (code machine de niveau - c'est à dire JIT). Comme les getter/setter trivial (c'est à dire très simple code) les appels de méthode sont détruits et les getter/setter écrit dans le code environnant.

Cela ne se produit pas en mode debug afin de soutenir le débogage (c'est à dire la capacité à définir un point d'arrêt dans un getter ou un setter).

Dans visual studio, il n'y a aucun moyen de le faire que dans le débogueur. Compiler en release, exécuter sans joint le débogueur et vous obtiendrez la pleine optimisation.

Je ne crois pas que dans la vraie demande où ces propriétés sont utilisées dans beaucoup plus évoluée de la manière dont ils vont être optimisées de la même façon.

Le monde est plein d'illusions qui sont mauvais. Ils seront optimisés qu'ils sont encore trivial (c'est à dire un code simple, de sorte qu'ils sont inline).

4voto

Asik Points 6599

Il convient de noter qu'il est possible de voir la "vraie" performance dans Visual Studio.

  1. Compiler en mode Release avec les Optimisations activées.
  2. Aller à Déboguer -> Options et de Paramètres et décochez la case "Supprimer JIT optimisation sur le module de chargement (Géré uniquement)".
  3. En option, décochez la case "Activer uniquement Mon Code", sinon vous ne pourrez peut-être pas dans le code.

Maintenant, le jitted de l'assemblée sera le même, même avec le débogueur, vous permettant d'étape dans l'optimisation des dissassembly si vous s'il vous plaît. C'est essentiel pour comprendre comment le CLR optimise le code.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X