[C++] Performances C ++ d'accès aux variables membres par rapport aux variables locales


Answers

Je préfère les variables locales sur les principes généraux, car elles minimisent l'état mutable mal dans votre programme. En ce qui concerne les performances, votre profileur vous dira tout ce que vous devez savoir. Les sections locales devraient être plus rapides pour les ints et peut-être d'autres builtins, parce qu'ils peuvent être mis dans des registres.

Question

Est-il plus efficace pour une classe d'accéder à des variables membres ou à des variables locales? Par exemple, supposons que vous ayez une méthode (callback) dont la seule responsabilité est de recevoir des données, d'effectuer des calculs sur celles-ci, puis de les transmettre à d'autres classes. Au niveau des performances, est-il plus logique d'avoir une liste de variables membres que la méthode remplit lorsqu'elle reçoit des données? Ou simplement déclarer les variables locales chaque fois que la méthode de rappel est appelée?

Supposons que cette méthode serait appelée des centaines de fois par seconde ...

Au cas où je ne serais pas clair, voici quelques exemples rapides:

// use local variables
class thisClass {
    public:
        void callback( msg& msg )
        {
            int varA;
            double varB;
            std::string varC;
            varA = msg.getInt();
            varB = msg.getDouble();
            varC = msg.getString();

            // do a bunch of calculations
         }

};

// use member variables
class thisClass {
    public:
        void callback( msg& msg )
        {
             m_varA = msg.getInt();
             m_varB = msg.getDouble();
             m_varC = msg.getString();

             // do a bunch of calculations
        }

    private:
        int m_varA;
        double m_varB;
        std::string m_varC;

};



Quelques points qui n'ont pas été explicitement mentionnés par d'autres:

  • Vous appelez potentiellement des opérateurs d'affectation dans votre code. par exemple varC = msg.getString ();

  • Vous avez des cycles gaspillés à chaque fois que le cadre de fonction est configuré. Vous créez des variables, appelez le constructeur par défaut, puis appelez l'opérateur d'affectation pour obtenir la valeur RHS dans les sections locales.

  • Déclarez les locaux pour qu'ils soient const-refs et, bien sûr, les initialiser.

  • Les variables membres peuvent être sur le tas (si votre objet y a été affecté) et souffrent donc de la non-localité.

  • Même quelques cycles sauvegardés sont bons - pourquoi perdre du temps de calcul, si vous pouviez l'éviter.




Cela devrait être votre problème de compilateurs. Au lieu de cela, optimisez pour la maintenabilité: Si l'information est seulement utilisée localement, stockez-la dans des variables locales (automatiques). Je déteste lire des classes jonchées de variables membres qui ne me disent rien sur la classe elle-même, mais seulement quelques détails sur la façon dont un tas de méthodes fonctionnent ensemble :(

En fait, je serais surpris si les variables locales ne sont pas plus rapides - elles sont forcément en cache, car elles sont proches du reste des données de fonctions (frame d'appel) et un pointeur d'objets peut être quelque part ailleurs - mais Je devine juste ici.




La quantité de données avec laquelle vous allez interagir aura une plus grande influence sur la vitesse d'exécution que la façon dont vous représentez les données dans l'implémentation de l'algorithme.

Le processeur ne se soucie pas vraiment si les données sont sur la pile ou sur le tas (en dehors de la chance que le haut de la pile sera dans le cache du processeur comme peterchen mentionné) mais pour une vitesse maximale, les données devront s'intégrer dans le cache du processeur (cache L1 si vous avez plus d'un niveau de cache, ce qui est le cas de tous les processeurs modernes). Toute charge du cache L2 - ou $ DEITY interdid, mémoire principale - ralentira l'exécution. Donc, si vous traitez une chaîne d'une taille de quelques centaines de Ko et des chances à chaque invocation, la différence ne sera même pas mesurable.

Gardez à l'esprit que dans la plupart des cas, une accélération de 10% dans un programme est pratiquement indétectable pour l'utilisateur final (sauf si vous parvenez à réduire le temps d'exécution de votre lot de nuit à moins de 24h). à moins que vous ne soyez sûr et que vous ayez la sortie du profileur pour sauvegarder que ce morceau de code se trouve dans la zone chaude de 10% -20% qui a une influence majeure sur l'exécution de votre programme.

D'autres considérations devraient être plus importantes, comme la maintenabilité ou d'autres facteurs externes. Par exemple, si le code ci-dessus est en code fortement multithread, l'utilisation de variables locales peut faciliter l'implémentation.




L'utilisation des variables membres devrait être légèrement plus rapide puisqu'elles ne doivent être allouées qu'une seule fois (lorsque l'objet est construit) au lieu de chaque fois que le rappel est appelé. Mais en comparaison avec le reste du travail que vous faites probablement, je m'attends à ce que ce soit un très petit pourcentage. Benckmark à la fois et voir qui est le plus rapide.