Boost logo

Boost :

Subject: Re: [boost] [function] function wrapping withnoexceptionsafetyguarantee
From: Daniel Walker (daniel.j.walker_at_[hidden])
Date: 2010-11-06 15:44:57


On Sat, Nov 6, 2010 at 2:08 PM, Emil Dotchevski <emil_at_[hidden]> wrote:
> On Sat, Nov 6, 2010 at 10:22 AM, Daniel Walker
> <daniel.j.walker_at_[hidden]> wrote:
>> On Tue, Nov 2, 2010 at 7:20 PM, Jeffrey Lee Hellrung, Jr.
>> <jhellrung_at_[hidden]> wrote:
>>> On 11/02/2010 02:50 PM, Daniel Walker wrote:
>>> [...]
>>>>
>>>> Here are the results I got, again, using the build of g++ 4.2 provided
>>>> by my manufacturer.
>>>>
>>>> Data (Release):
>>>>            |  function   | function (static empty)
>>>> time/call  |  3.54e-07s  |  3.51e-07s
>>>> space/type |    64B      |    80B
>>>>
>>>> Data (Debug):
>>>>            |  function   | function (static empty)
>>>> time/call  |  2.05e-06s  |  2.04e-06s
>>>> space/type |    64B      |    80B
>>>>
>>>> You can see that removing the empty check from boost::function yields
>>>> about a 1% improvement in time per call to boost::signal. The
>>>> increased space per type overhead is the same as before: 16B.
>>>
>>> [...]
>>>
>>> [Butting in after only vaguely following this thread...]
>>>
>>> Would it also be appropriate to measure the "space/call", in addition to
>>> "time/call" and "space/type"?  Or is there no difference, or had this been
>>> addressed already?
>>
>> Well, a call to boost::function does not cost any additional space.
>> However, there is a space/object cost, which the other benchmark does
>> measure. The space overhead per boost::function object is constant. On
>> my machine it's 32B for both of the empty state schemes.
>
> Can someone please explain why does storing the empty state take space per type?

Storing a target function takes space per type, namely, the static
stored_vtable on line 912 of boost/function/function_template.hpp,
which is dependent on both the type of boost::funciton's signature and
the type of the target function. If the empty state is represented by
a special "empty" target function, then this requires space to store
the "empty" target function.

We can move around where that space is consumed: it could be in the
writable, initialized static data section, or we could move it to
constant static data in the text segment. Regardless, the empty state
must be either represented using memory or computed dynamically. As
they say, there's no such thing as a free lunch. If boost::function is
going to have two states, then those two states come at a cost. We can
pay for them with either an extra static vtable in the executable or
an extra pointer comparison, which in many cases can be optimized away
by the compiler. The exact expense depends on the user's circumstance,
which is why I think users should have the option to choose between
the two schemes.

Daniel Walker


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk