Dans la conception de ma classe, j'utilise beaucoup de classes abstraites et de fonctions virtuelles. J'avais le sentiment que les fonctions virtuelles affectaient les performances. Est-ce vrai? Mais je pense que cette différence de performance n'est pas perceptible et il semble que je fasse une optimisation prématurée. Droite?
c++
performance
optimization
virtual-functions
Navaneeth KN
la source
la source
Réponses:
Une bonne règle de base est:
L'utilisation de fonctions virtuelles aura un très léger effet sur les performances, mais il est peu probable que cela affecte les performances globales de votre application. Les algorithmes et les E / S sont de meilleurs endroits pour rechercher des améliorations de performances.
Un excellent article qui parle des fonctions virtuelles (et plus) est les pointeurs de fonction de membre et les délégués C ++ les plus rapides possibles .
la source
Votre question m'a rendu curieux, alors je suis allé de l'avant et j'ai exécuté quelques timings sur le processeur PowerPC 3GHz dans l'ordre avec lequel nous travaillons. Le test que j'ai effectué était de créer une simple classe vectorielle 4d avec des fonctions get / set
Ensuite, j'ai mis en place trois tableaux contenant chacun 1024 de ces vecteurs (assez petits pour tenir dans L1) et j'ai exécuté une boucle qui les a ajoutés les uns aux autres (Ax = Bx + Cx) 1000 fois. J'ai couru cela avec les fonctions définies comme
inline
,virtual
et les appels de fonctions régulières. Voici les résultats:Ainsi, dans ce cas (où tout tient dans le cache), les appels de fonction virtuelle étaient environ 20 fois plus lents que les appels en ligne. Mais qu'est-ce que cela signifie vraiment? Chaque voyage dans la boucle provoquait exactement
3 * 4 * 1024 = 12,288
des appels de fonction (1024 vecteurs fois quatre composants multipliés par trois appels par ajout), donc ces temps représentent1000 * 12,288 = 12,288,000
des appels de fonction. La boucle virtuelle prenait 92 ms de plus que la boucle directe, de sorte que la surcharge supplémentaire par appel était de 7 nanosecondes par fonction.De cela, je conclus: oui , les fonctions virtuelles sont beaucoup plus lentes que les fonctions directes, et non , à moins que vous ne prévoyiez de les appeler dix millions de fois par seconde, cela n'a pas d'importance.
Voir aussi: comparaison de l'assemblage généré.
la source
Lorsque Objective-C (où toutes les méthodes sont virtuelles) est le langage principal de l'iPhone et que le freakin ' Java est le langage principal pour Android, je pense qu'il est assez sûr d'utiliser les fonctions virtuelles C ++ sur nos tours dual-core 3 GHz.
la source
Dans les applications très performantes (comme les jeux vidéo), un appel de fonction virtuelle peut être trop lent. Avec le matériel moderne, le plus gros problème de performances est le manque de cache. Si les données ne sont pas dans le cache, il peut s'écouler des centaines de cycles avant qu'elles ne soient disponibles.
Un appel de fonction normal peut générer un échec du cache d'instructions lorsque le processeur récupère la première instruction de la nouvelle fonction et qu'elle n'est pas dans le cache.
Un appel de fonction virtuelle doit d'abord charger le pointeur vtable à partir de l'objet. Cela peut entraîner un échec du cache de données. Ensuite, il charge le pointeur de fonction de la vtable, ce qui peut entraîner un autre échec du cache de données. Ensuite, il appelle la fonction qui peut entraîner un échec du cache d'instructions comme une fonction non virtuelle.
Dans de nombreux cas, deux échecs de cache supplémentaires ne sont pas un problème, mais dans une boucle serrée sur le code critique de performances, cela peut réduire considérablement les performances.
la source
À partir de la page 44 du manuel "Optimizing Software in C ++" d' Agner Fog :
la source
switch
. Avec descase
valeurs totalement arbitraires , bien sûr. Mais si tous lescase
s sont consécutifs, un compilateur pourrait être en mesure d'optimiser cela en une table de saut (ah, qui me rappelle les bons vieux jours du Z80), qui devrait être (faute d'un meilleur terme) à temps constant. Non pas que je recommande d'essayer de remplacer les vfuncs parswitch
, ce qui est ridicule. ;)absolument. C'était un problème à l'époque où les ordinateurs fonctionnaient à 100Mhz, car chaque appel de méthode nécessitait une recherche sur la vtable avant d'être appelé. Mais aujourd'hui ... sur un processeur 3Ghz qui a un cache de 1er niveau avec plus de mémoire que mon premier ordinateur? Pas du tout. Allouer de la mémoire à partir de la RAM principale vous coûtera plus de temps que si toutes vos fonctions étaient virtuelles.
C'est comme le bon vieux temps où les gens disaient que la programmation structurée était lente parce que tout le code était divisé en fonctions, chaque fonction nécessitait des allocations de pile et un appel de fonction!
La seule fois où je penserais même à prendre la peine de considérer l'impact sur les performances d'une fonction virtuelle, c'est si elle était très largement utilisée et instanciée dans un code basé sur un modèle qui s'est retrouvé dans tout. Même dans ce cas, je n'y consacrerais pas trop d'efforts!
PS pense à d'autres langages «faciles à utiliser» - toutes leurs méthodes sont virtuelles sous les couvertures et elles ne rampent pas de nos jours.
la source
Il y a un autre critère de performance en plus du temps d'exécution. Une Vtable prend également de l'espace mémoire et, dans certains cas, peut être évitée: ATL utilise une " liaison dynamique simulée " à la compilation avec des modèlespour obtenir l'effet du «polymorphisme statique», ce qui est assez difficile à expliquer; vous passez essentiellement la classe dérivée en tant que paramètre à un modèle de classe de base, de sorte qu'au moment de la compilation, la classe de base "sait" quelle est sa classe dérivée dans chaque instance. Ne vous permettra pas de stocker plusieurs classes dérivées différentes dans une collection de types de base (c'est le polymorphisme à l'exécution) mais d'un sens statique, si vous voulez créer une classe Y identique à une classe de modèle préexistante X qui a le hooks pour ce genre de surcharge, il vous suffit de remplacer les méthodes qui vous intéressent, puis vous obtenez les méthodes de base de la classe X sans avoir à avoir une vtable.
Dans les classes avec de grandes empreintes mémoire, le coût d'un seul pointeur vtable n'est pas beaucoup, mais certaines des classes ATL dans COM sont très petites, et cela vaut les économies de vtable si le cas de polymorphisme d'exécution ne se produira jamais.
Voir aussi cette autre question SO .
En passant, voici un article que j'ai trouvé qui parle des aspects de performance du temps CPU.
la source
Oui, vous avez raison et si vous êtes curieux de connaître le coût de l'appel de fonction virtuelle, vous pourriez trouver ce post intéressant.
la source
La seule façon dont je peux voir qu'une fonction virtuelle deviendra un problème de performances est si de nombreuses fonctions virtuelles sont appelées dans une boucle serrée, et si et seulement si elles provoquent une erreur de page ou une autre opération de mémoire «lourde».
Bien que, comme d'autres l'ont dit, cela ne sera pratiquement jamais un problème pour vous dans la vraie vie. Et si vous pensez que c'est le cas, exécutez un profileur, effectuez des tests et vérifiez si cela pose vraiment un problème avant d'essayer de «annuler la conception» de votre code pour améliorer les performances.
la source
Lorsque la méthode de classe n'est pas virtuelle, le compilateur effectue généralement l'in-line. Au contraire, lorsque vous utilisez un pointeur vers une classe avec une fonction virtuelle, l'adresse réelle ne sera connue qu'au moment de l'exécution.
Ceci est bien illustré par le test, décalage horaire ~ 700% (!):
L'impact de l'appel de fonction virtuelle dépend fortement de la situation. S'il y a peu d'appels et une quantité importante de travail à l'intérieur de la fonction - cela pourrait être négligeable.
Ou, quand il s'agit d'un appel virtuel utilisé à plusieurs reprises, tout en effectuant une opération simple - cela peut être très important.
la source
++ia
. Et alors?J'ai fait des allers-retours sur cela au moins 20 fois sur mon projet particulier. Bien qu'il puisse y avoir de grands gains en termes de réutilisation du code, de clarté, de maintenabilité et de lisibilité, en revanche, les performances sont toujours valables. exister avec des fonctions virtuelles.
La performance sera-t-elle perceptible sur un ordinateur portable / bureau / tablette moderne ... probablement pas! Cependant, dans certains cas avec des systèmes embarqués, la baisse des performances peut être le facteur déterminant de l'inefficacité de votre code, en particulier si la fonction virtuelle est appelée maintes et maintes fois en boucle.
Voici un article daté qui analyse les meilleures pratiques pour C / C ++ dans le contexte des systèmes embarqués: http://www.open-std.org/jtc1/sc22/wg21/docs/ESC_Boston_01_304_paper.pdf
Pour conclure: c'est au programmeur de comprendre les avantages / inconvénients de l'utilisation d'une certaine construction par rapport à une autre. À moins que vous ne soyez axé sur les performances, vous ne vous souciez probablement pas de l'atteinte des performances et devriez utiliser toutes les astuces OO en C ++ pour rendre votre code aussi utilisable que possible.
la source
D'après mon expérience, le principal élément pertinent est la capacité à intégrer une fonction. Si vous avez des besoins en performances / optimisation qui imposent qu'une fonction doit être intégrée, vous ne pouvez pas rendre la fonction virtuelle car cela empêcherait cela. Sinon, vous ne remarquerez probablement pas la différence.
la source
Une chose à noter est que ceci:
peut être plus rapide que cela:
En effet, la première méthode n'appelle qu'une seule fonction tandis que la seconde peut appeler de nombreuses fonctions différentes. Cela s'applique à toute fonction virtuelle dans n'importe quelle langue.
Je dis "peut" parce que cela dépend du compilateur, du cache, etc.
la source
La pénalité de performance liée à l'utilisation de fonctions virtuelles ne peut jamais surpasser les avantages que vous obtenez au niveau de la conception. On suppose qu'un appel à une fonction virtuelle serait 25% moins efficace qu'un appel direct à une fonction statique. C'est parce qu'il existe un niveau d'indirection via le VMT. Cependant, le temps nécessaire pour effectuer l'appel est normalement très petit par rapport au temps nécessaire à l'exécution réelle de votre fonction, de sorte que le coût total des performances sera négligeable, en particulier avec les performances actuelles du matériel. De plus, le compilateur peut parfois optimiser et voir qu'aucun appel virtuel n'est nécessaire et le compiler en un appel statique. Alors ne vous inquiétez pas, utilisez autant de fonctions virtuelles et de classes abstraites que nécessaire.
la source
The performance penalty of using virtual functions can sometimes be so insignificant that it is completely outweighed by the advantages you get at the design level.
La principale différence est de diresometimes
, nonnever
.Je me suis toujours posé la question, d'autant plus que - il y a quelques années - j'ai également fait un tel test comparant les horaires d'un appel de méthode de membre standard avec un appel virtuel et j'étais vraiment en colère contre les résultats à ce moment-là, ayant des appels virtuels vides étant 8 fois plus lent que les non-virtuels.
Aujourd'hui, je devais décider d'utiliser ou non une fonction virtuelle pour allouer plus de mémoire dans ma classe de tampon, dans une application très critique pour les performances, alors j'ai cherché sur Google (et vous ai trouvé), et à la fin, j'ai refait le test.
Et j'ai été vraiment surpris que cela - en fait - n'ait vraiment plus d'importance. Bien qu'il soit logique d'avoir des inlines plus rapides que les non-virtuels, et qu'ils soient plus rapides que les virtuels, il s'agit souvent de la charge de l'ordinateur dans son ensemble, de savoir si votre cache contient les données nécessaires ou non, et même si vous pourrez peut-être optimiser au niveau du cache, je pense que cela devrait être fait par les développeurs du compilateur plus que par les développeurs d'applications.
la source