2017-03-09 2 views
1

Je suis tombé sur un tutoriel d'Alexandrescu sur les traits et j'ai quelques réflexions à partager. Voici le code:Traits vs overhead virtuel

// Example 6: Reference counting traits 
// 
template <class T> 
class RefCountingTraits 
{ 
    static void Refer(T* p) 
    { 
    p->IncRef(); // assume RefCounted interface 
    } 

    static void Unrefer(T* p) 
    { 
    p->DecRef(); // assume RefCounted interface 
    } 
}; 

template <> 
class RefCountingTraits<Widget> 
{ 
    static void Refer(Widget* p) 
    { 
    p->AddReference(); // use Widget interface 
    } 
    static void Unrefer(Widget* p) 
    { 
    // use Widget interface 
    if (p->RemoveReference() == 0) 
     delete p; 
    } 
}; 

Combien les frais généraux que nous avons dans ce cas par rapport à un membre de la fonction virtuelle cas standard? nous n'accédons pas directement à l'objet aussi dans ce cas: nous passons toujours un pointeur. Le compilateur est-il capable de l'optimiser de la même manière?

Répondre

1

Aux niveaux d'optimisation de production standard (-O2 ou /O2), vous pouvez vous attendre à ce que tout le code que vous avez indiqué soit aligné et que les bits sans effets secondaires soient optimisés. Cela laisse les appels réels à IncRef ou AddReference et le chèque pour et delete -ion. Si les fonctions virtual ont été utilisées, et si le code de comptage de référence est trivial (par exemple, non thread-safe), il peut avoir été plus lent d'un ordre de grandeur en raison d'une recherche de table de répartition et d'un appel de fonction hors ligne , mais cela va varier un peu avec le compilateur, les paramètres d'optimisation exacts, le CPU, les conventions d'appel, etc.

Comme toujours, lorsque vous devez vous soucier, faire des profils et expérimenter.

+0

Si j'ai bien compris, ce code, une fois optimisé, ressemblera à appeler directement p-> IncRef(), sans la copie du pointeur droite? il semble trop un ordre de grandeur. Plein accord sur le profilage :) – user3770392

+0

* "... pas vrai?" * Right. * "trop ​​d'un ordre de grandeur" * - même l'appel contrasté d'une fonction triviale sélectionnée par un commutateur d'exécution vs l'envoi virtuel a donné un facteur 9.2x dans [ce benchmark] (http://stackoverflow.com/a/4801861/410767), mais toujours utile pour mesurer et partager votre propre code de référence/résultats. Dans ce cas, le 'IncRef()' 'DecRef()' n'est probablement pas si trivial lorsque la sécurité du thread est nécessaire, donc l'impact de l'envoi virtuel supplémentaire sera un facteur plus petit. –

+0

merci pour les explications :) – user3770392