boost::function2's copy constructor expensive - why?
Hi! Today's profiling of my code (which massively uses boost::function to collect formulas) showed that boost::function2' copy constructor is called zillions of times. OK, I disabled inlining to get some more details, but this I do not understand. The functors are created, stored in an array and do not get copied again, but rather referenced there. Before I dig in that code: where do those copies come from? Is that the normal behaviour triggered ny operator() or is that a hint that I use them the wrong way? Any experience? At present the boost::function overhead kills my application. Tuning tipps? best regards, Markus
On Monday 10 February 2003 07:19 am, Markus Werle wrote:
Before I dig in that code: where do those copies come from? Is that the normal behaviour triggered ny operator() or is that a hint that I use them the wrong way?
operator() will not make any copies. The overhead of operator() comes from calls through function pointers. The most likely reason I can think of for the multitude of copy constructions after the array is built is that you are passing boost::function2 objects to routines that take function objects by value. Unfortunately, this is the common way to pass function objects, e.g., template<typename F> void do_something(F f) { ... } If you are using the C++ standard library algorithms, that may be your culprit. You can pass a "reference" to those algorithms by changing 'f' parameters to: boost::bind(ref(f), _1, _2) Doug
Douglas Gregor wrote:
On Monday 10 February 2003 07:19 am, Markus Werle wrote:
Before I dig in that code: where do those copies come from? Is that the normal behaviour triggered ny operator() or is that a hint that I use them the wrong way?
operator() will not make any copies. The overhead of operator() comes from calls through function pointers.
The most likely reason I can think of for the multitude of copy constructions after the array is built is that you are passing boost::function2 objects to routines that take function objects by value. Unfortunately, this is the common way to pass function objects, e.g.,
template<typename F> void do_something(F f) { ... }
If you are using the C++ standard library algorithms,
Yeah, that's it. std::algos everywhere.
that may be your culprit.
I think yes.
You can pass a "reference" to those algorithms by changing 'f' parameters to: boost::bind(ref(f), _1, _2)
Do I need this only in the outermost binding level (I have nested boost::functions) or do I have to apply "ref" also to the original (true, existent) functions at the leaves of the functor tree? Markus
On Monday 10 February 2003 12:29 pm, Markus Werle wrote:
You can pass a "reference" to those algorithms by changing 'f' parameters to: boost::bind(ref(f), _1, _2)
Do I need this only in the outermost binding level (I have nested boost::functions) or do I have to apply "ref" also to the original (true, existent) functions at the leaves of the functor tree?
You only need this at the outermost binding level. Doug
Douglas Gregor wrote:
On Monday 10 February 2003 12:29 pm, Markus Werle wrote:
You can pass a "reference" to those algorithms by changing 'f' parameters to: boost::bind(ref(f), _1, _2)
Do I need this only in the outermost binding level (I have nested boost::functions) or do I have to apply "ref" also to the original (true, existent) functions at the leaves of the functor tree?
You only need this at the outermost binding level.
OK. Q: I am pretty unsure about dangling references. My function object creator functions return boost::functions by value (and collect these form others). If the root function object creator wraps its stuff in a cref: does boost lib take care for the lifetime of the object? How does this work? Markus
On Monday 10 February 2003 03:32 pm, Markus Werle wrote:
Q: I am pretty unsure about dangling references. My function object creator functions return boost::functions by value (and collect these form others).
If the root function object creator wraps its stuff in a cref: does boost lib take care for the lifetime of the object? How does this work?
Passing a copy of ref(x) or cref(x) is just like passing x by reference: there is no transform of ownership, so the Boost lib will _not_ take care of the lifetime for you. ref/cref is well-suited for cheaply passing function objects to standard algorithms, but you probably don't want to stick a ref/cref'd function object into a boost::function object unless you can be _sure_ that the function object will live longer that the boost::function object. In the program you described, you'd probably want to keep your array of boost::function objects but use the bind/(c)ref syntax for passing function objects to standard algorithms. Doug
participants (2)
-
Douglas Gregor
-
Markus Werle