Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does boost::bind cause overhead?

I am currently working on network software. It has one main class, server which obviously represents a server instance.

A server instance can send requests and the user is notified of the response by a callback.

The code is like:

class server
{
  public:
    typedef boost::function<void (int duration)> callback_func;

    void send_request(endpoint& ep, callback_func cb);
};

Now let's say that, as a user I want to the callback to know about the instance that called it, I can do the following thing:

void mycallback(const server& sv, int duration) { ... }

server sv;
sv.send_request("localhost", boost::bind(&mycallback, boost::ref(sv), _1));

But I wonder: is there any overhead doing so ? Will the calls to mycallback be any slower than using a "regular" call ?

Thank you.

Foot note: I could of course change my typedef to: typedef boost::function<void (const server& sv, int duration)> callback_func; and if boost::bind cause any significant overhead, that's probably what I will do in the end. I would just like to know what costs implies the use of boost::bind.

like image 282
ereOn Avatar asked May 05 '11 08:05

ereOn


4 Answers

Of course it causes overhead. What it does is that it creates a functor that stores the bound parameters and has an operator() that you call with the remaining arguments. Now, is this significant? I don't know, because that is just a word. Make 10 million requests and measure it. You are the only one who can tell if this overhead is significant to you or not.

Also, I faced a similar problem. Since I didn't really need delegates, I could get away with function pointers. But I found an interesting benchmark which also mentions some alternative implementation, all of them with better performance than boost::function. This comes at the cost of portability and in some cases ugly, non-standard hacks in the implementation (but a really good performance in return).

like image 196
Tamás Szelei Avatar answered Sep 24 '22 22:09

Tamás Szelei


boost::bind generates a functional object which can be optimized out if it is used as argument to function templates, but boost::function prevents this optimization, just like passing a pointer to a function will prevent its inlining. boost::function itself need not introduce more overhead than a virtual function all or call via a pointer to function.

PS. I agree with Tamás Szelei: make 10 million requests and measure it.

like image 35
Begemoth Avatar answered Sep 24 '22 22:09

Begemoth


Compared to a normal function call, you're paying for two indirections for the function call, which is similar to the overhead of a (non-devirtualised) virtual function call.

The first indirection is due to the type erasure that happens in boost::function (this is documented in the boost::function documentation). This one cannot really be optimized, and you'd have the same penalty with a naked function pointer, too.

The second indirection comes from calling the mycallback function through a function pointer. A very well-optimising compiler can figure this out and optimise this out, but a normal compiler won't. You can get rid of this indirection (in all compilers) if you turn mycallback into a function object:

Instead of

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

you do

struct mycallback {
    void operator()( .1. ) const { .2. }
};
like image 26
Marc Mutz - mmutz Avatar answered Sep 24 '22 22:09

Marc Mutz - mmutz


Be aware that boost::bind causes a copy of the functor. This can be very significant. For my operating system news and deletes are very expensive. See boost::bind documentation about ref() and cref(). I believe that member functions also cause functor copies but there is no documentation about that.

like image 25
Ant Avatar answered Sep 23 '22 22:09

Ant