Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

function<>-optimizations

14 views
Skip to first unread message

Bonita Montero

unread,
Sep 12, 2022, 8:01:14 AM9/12/22
to
I wondered why a std::function has 64 bytes in size with MSVC.
I compiled the following code and disassembled it.

#include <iostream>
#include <functional>
#include <string_view>

using namespace std;

int main()
{
string_view
sv( "hello" ),
sv2( "wolrld" );
function<void ()> fn( [sv, sv2]() { cout << sv << " " << sv2 << endl; } );
cout << sizeof fn << endl;
fn();
}

The function object passed to the fn constructor has two captures,
i.e. it isn't a normal C-callable so that you might expect that
the constructor of the function<>-object allocates external memory
for that.
But because of its size I expected function<> to have sth. like a
small string optimization, thereby including the whole function
object in its own body up to a certain size. And the disassembly
showed that my expectations were right.
With libstdc++ function<>-objects are 32 bytes in size, so you
won't have to expect that there's some optimization like this.
Is there any mailing list of libstdc++ where I can suggest
such an optimization ?

Paavo Helde

unread,
Sep 12, 2022, 8:30:02 AM9/12/22
to
12.09.2022 15:01 Bonita Montero kirjutas:
> I wondered why a std::function has 64 bytes in size with MSVC.
> I compiled the following code and disassembled it.
>
> #include <iostream>
> #include <functional>
> #include <string_view>
>
> using namespace std;
>
> int main()
> {
>     string_view
>         sv( "hello" ),
>         sv2( "wolrld" );
>     function<void ()> fn( [sv, sv2]() { cout << sv << " " << sv2 <<
> endl; } );
>     cout << sizeof fn << endl;
>     fn();
> }
>
> The function object passed to the fn constructor has two captures,
> i.e. it isn't a normal C-callable so that you might expect that
> the constructor of the function<>-object allocates external memory
> for that.
> But because of its size I expected function<> to have sth. like a
> small string optimization, thereby including the whole function
> object in its own body up to a certain size. And the disassembly
> showed that my expectations were right.

That's strange because the compiler would be buggy if it copied the
string content when only asked to copy a string_view. And indeed, a
little modification to your program proves that the string content is
not contained in the function object, so there is no SSO needed or used:

#include <iostream>
#include <functional>
#include <string_view>

int main() {
char hello[] = "hello";
char world[] = "world";
std::string_view sv(hello), sv2(world);
std::function<void()> fn([sv, sv2]() { std::cout << sv << " " <<
sv2 << std::endl; });
std::cout << sizeof fn << std::endl;

const char* adieu = "adieu";
std::copy(adieu, adieu + sizeof hello, hello);
fn(); // outputs: adieu world
}



Bonita Montero

unread,
Sep 12, 2022, 9:38:11 AM9/12/22
to
Am 12.09.2022 um 14:29 schrieb Paavo Helde:

> That's strange because the compiler would be buggy if it copied the
> string content when only asked to copy a string_view. ...

That's not what I wanted to say. The string_views are copied into the
lambda object and the lambda object is copied into the function<> object
as wole without any external allocations. So the function<>-object has
some space for small function-objects passed to its constructor.


Paavo Helde

unread,
Sep 12, 2022, 10:43:07 AM9/12/22
to
Ah, I see. It seems I misread your original post. Yes it seems the
lambda arguments up to 48 bytes are passed as embedded inside the
std::function object, with MSVC.


0 new messages