Est-ce que boost :: bind cause des frais généraux?

Je travaille actuellement sur un logiciel de réseau. Il a une classe principale, server qui représente évidemment une instance de serveur.

Une instance de server peut envoyer des demandes et l’utilisateur est averti de la réponse par un rappel.

Le code est comme:

 class server { public: typedef boost::function callback_func; void send_request(endpoint& ep, callback_func cb); }; 

Maintenant, disons que, en tant qu’utilisateur, je souhaite que le rappel connaisse l’instance qui l’a appelée, je peux effectuer les opérations suivantes:

 void mycallback(const server& sv, int duration) { ... } server sv; sv.send_request("localhost", boost::bind(&mycallback, boost::ref(sv), _1)); 

Mais je me demande: y at-il des frais généraux qui le font? Est-ce que les appels vers mycallback seront plus lents que d’utiliser un appel “normal”?

Je vous remercie.

Note de bas de page: je pourrais bien sûr changer mon typedef en: typedef boost::function callback_func; et si boost::bind cause une surcharge importante, c’est probablement ce que je ferai à la fin. Je voudrais juste savoir quels coûts impliquent l’utilisation de boost::bind .

Bien sûr, cela cause des frais généraux. Cela crée un foncteur qui stocke les parameters liés et un operator() que vous appelez avec les arguments restants. Maintenant, est-ce important? Je ne sais pas, parce que ce n’est qu’un mot. Faites 10 millions de demandes et mesurez-le. Vous êtes le seul à pouvoir dire si ces frais généraux sont importants pour vous ou non.

En outre, j’ai rencontré un problème similaire. Comme je n’avais pas vraiment besoin de delegates, je pouvais m’en tirer avec des indicateurs de fonction. Mais j’ai trouvé un repère intéressant qui mentionne également une implémentation alternative, toutes plus performantes que boost::function . Cela se fait au désortingment de la portabilité et, dans certains cas, de laids, hacks non standard dans la mise en œuvre (mais une très bonne performance en retour).

boost::bind génère un object fonctionnel qui peut être optimisé s’il est utilisé comme argument pour les modèles de fonction, mais boost::function empêche cette optimisation, tout comme le passage d’un pointeur à une fonction empêchera son inline. boost::function lui-même n’a pas besoin d’introduire plus de temps système qu’une fonction virtuelle ou d’appeler via un pointeur pour fonctionner.

PS Je suis d’accord avec Tamás Szelei: faites 10 millions de demandes et mesurez-le.

Par rapport à un appel de fonction normal, vous payez deux indirections pour l’appel de fonction, ce qui est similaire à la surcharge d’un appel de fonction virtuel (non dévirtualisé).

La première indirection est due au type effacement qui se produit dans boost :: function (ceci est documenté dans la documentation de boost::function ). Celui-ci ne peut pas vraiment être optimisé, et vous auriez aussi la même pénalité avec un pointeur de fonction nue.

La deuxième indirection provient de l’appel de la fonction mycallback via un pointeur de fonction. Un compilateur très optimiste peut comprendre cela et l’optimiser, mais pas un compilateur normal. Vous pouvez vous débarrasser de cette indirection (dans tous les compilateurs) si vous transformez mycallback en object function:

Au lieu de

 void mycallback( .1. ) { .2. } 

tu fais

 struct mycallback { void operator()( .1. ) const { .2. } }; 

Sachez que boost :: bind provoque une copie du foncteur. Cela peut être très important. Pour mon système d’exploitation, les nouvelles et les suppressions sont très coûteuses. Voir la documentation de boost :: bind sur ref () et cref (). Je crois que les fonctions membres causent également des copies de foncteur, mais il n’ya pas de documentation à ce sujet.