2011-10-09 3 views
1

Cette question est plus ou moins similaire à cette Extend an existing API: Use default argument or wrapper function? mais suffisamment différente.
S'il vous plaît lire.Combien de frais généraux dois-je attendre d'une fonction d'emballage

J'ai une classe Foo qui a la fonction oldFunc qui est utilisée dans plusieurs parties de mon programme.
Afin d'introduire un nouveau comportement à Foo j'ai implémenté newFunc et l'ai rendu privé de sorte que
les appelants à oldFunc continuent à utiliser la même API mais peuvent obtenir le nouveau comportement s'ils définissent un drapeau par appelant la fonction setUseType().

pseudo-code suivant:

class Foo 
{ 
public: 
    Foo(){ useNew = false;} 
    void setUseType(bool useType){ useNew = useType;} 
    std::string oldFunc(int r) 
    { 
    if(useNew) 
    { 
     return newFunc(r); 
    } 
    return std::string("Some value after doing some work"); 
    } 
private: 
    std::string newFunc(int r){ return std::string("Some value after doing some work");} 
    bool useNew; 
}; 

QuestionoldFunc est appelée plusieurs fois (en millions de fois) à l'intérieur d'une boucle.
Combien de frais généraux dois-je attendre de l'emballage newFunc à l'intérieur oldFunc. En théorie, si et newFunc est implicite dans la mise en œuvre, y a-t-il une raison de s'attendre à ce que les appels avec un indicateur défini UseType(true) soient plus lents?

+1

cela semble être une manière fragile d'implémenter le versioning ...? –

+0

Est-ce que 'useNew' change au moment de l'exécution? Si ce n'est pas le cas, vous pouvez en faire une constante à la compilation et vous en débarrasser complètement. –

+0

@Kerrek SB 'useNew' est un paramètre d'exécution – user841550

Répondre

2

Dans ce cas particulier, il n'y aura pas de surcharge sur un compilateur non idiot car la fonction sera en ligne. Votre code serait équivalent à:

class Foo 
{ 
public: 
    Foo(){ useNew = false;} 
    void setUseType(bool useType){ useNew = useType;} 
    std::string oldFunc(int r) 
    { 
    if(useNew) 
    { 
     return std::string("Some value after doing some work");//newFunc inlined here 
    } 
    return std::string("Some value after doing some work"); 
    } 
private: 
    bool useNew; 
}; 

Si ce n'inline, il y aurait un saut supplémentaire pour l'appel à la nouvelle fonction. C'est là tout le temps de calcul supplémentaire. Ce saut supplémentaire entraînera probablement beaucoup moins de retard, même en tenant compte de millions d'appels. Je vous suggère de faire un profilage si vous avez vraiment des problèmes de vitesse et de déterminer le véritable goulot d'étranglement - probablement pas l'appel supplémentaire.

3

Vous pouvez le mesurer. Alors vous le savez à coup sûr. (Au moins à des fins de comparaison).

0

Je pense que tout compilateur moderne optimisera le code de telle sorte qu'il ne sera pas plus coûteux d'appeler newFunc() via oldFunc() que d'appeler oldFunc() directement. Mais notez que vous avez ajouté une instruction if qui sera évaluée chaque fois que oldFunc() est appelée, peu importe si vous utilisez les anciennes et nouvelles fonctions. Alors maintenant vous avez fait tous les appels à oldFunc() un peu plus lent.

La surcharge de l'ajout de l'instruction if pourrait être dans le bruit ou pourrait être significative, cela dépend. Vous devriez mesurer combien de temps il faut pour appeler l'original oldFunc() 1 000 000 fois, puis mesurer la même chose avec l'instruction if ajoutée. Si la différence est significative, vous pouvez rechercher d'autres façons de permettre au client de sélectionner la méthode à appeler pour éviter l'instruction if, par exemple via un pointeur de fonction membre.

Questions connexes