There have been proposals for C++ “delegates” which have lower overhead than boost::function:
- Member Function Pointers and the Fastest Possible C++ Delegates
- Fast C++ Delegate
- The Impossibly Fast C++ Delegates
Have any of those ideas been used to implement std::function, resulting in better performance than boost::function? Has anyone compared the performance of std::function vs boost::function?
I want to know this specifically for the GCC compiler and libstdc++ on Intel 64-bit architectures, but information on other compilers is welcome (such as Clang).
In libstdc++’s
std::functionwe use a union type that is suitably sized and aligned to store pointers, function pointers or pointers to member functions. We avoid a heap allocation for any function object that can be stored in that size and alignment, but only if it is “location invariant”The code is based on the
std::tr1::functionimplementation and that part hasn’t changed significantly. I think that could be simplified usingstd::aligned_storageand could be improved by specializing the trait so that more types are identified as location invariant.Invoking the target object is done without any virtual function calls, the type erasure is done by storing a single function pointer in the
std::functionwhich is the address of a function template specialization. All operations are done by calling that function template through the stored pointer and passing in an enum identifying what operation it is being asked to perform. This means no vtable and only a single function pointer needs to be stored in the object.This design was contributed by the original
boost::functionauthor and I believe it is close to the boost implementation. See the Performance docs for Boost.Function for some rationale. That means it’s pretty unlikely that GCC’sstd::functionis any faster thanboost::function, because it’s a similar design by the same person.N.B. our
std::functiondoesn’t support construction with an allocator yet, any allocations it needs to do will be done usingnew.In response to Emile’s comment expressing a desire to avoid a heap allocation for a
std::functionwhich holds a pointer to member function and an object, here’s a little hack to do it (but you didn’t hear it from me 😉The trick is that
InvokeAis small enough to fit in thefunction‘s small object buffer, and the trait specialization says it’s safe to store in there, so thefunctionholds a copy of that object directly, not on the heap. This requiresato persist as long as the pointer to it persists, but that would be the case anyway if thefunction‘s target wasbind(&A::foo, &a).