有快速代理背后的思想(等人)被用于优化的std ::功能? [英] Have the ideas behind the Fast Delegate (et al) been used to optimize std::function?
问题描述
有一直为C ++代表这比的boost ::功能开销较低的提案
:
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
有任何的这些想法被用来实施的std ::功能
,导致比的boost ::功能更好的性能
?有没有人比的std ::功能的性能
VS 的boost ::功能
?
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
?
我想知道这个专门为GCC编译器和libstdc ++基于英特尔64位架构,但对其他的编译器的信息是值得欢迎的(如锵)。
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).
推荐答案
在的libstdc ++的的std ::功能
我们使用的联合类型是合适的大小和对齐存储指针,函数指针或指针成员函数。我们避免了可以存储在大小和对齐方式的函数对象,堆分配,但只有当它是位置不变的
In libstdc++'s std::function
we 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"
/**
* Trait identifying "location-invariant" types, meaning that the
* address of the object (or any of its members) will not escape.
* Also implies a trivial copy constructor and assignment operator.
*/
在code是根据的std :: tr1 ::功能
的实施和部分没有显著改变。我认为,可以用的std :: aligned_storage
进行简化,使更多的类型被确定为位置可以通过专业的特点加以改进不变。
The code is based on the std::tr1::function
implementation and that part hasn't changed significantly. I think that could be simplified using std::aligned_storage
and could be improved by specializing the trait so that more types are identified as location invariant.
调用目标对象是没有任何虚函数调用来完成,类型擦除通过存储在的std ::功能
这是地址一个函数指针完成一个函数模板特殊化。所有操作都通过调用通过存储指针函数模板,并传递一个枚举确定它是被问什么要执行的操作完成。这意味着,没有虚函数表和仅一个单一的功能的指针需要被存储在对象
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::function
which 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.
这设计是贡献的原的boost ::功能
作者,我相信这是接近升压实施。见Boost.Function的效果文档一些理由。这意味着它是pretty不可能GCC的的std ::功能
是比任何的boost ::功能
,因为速度更快它是由同一个人了类似的设计。
This design was contributed by the original boost::function
author 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's std::function
is any faster than boost::function
, because it's a similar design by the same person.
N.B。我们的的std ::功能
不支持建设与分配器的是,它需要做的将使用进行任何分配新
。
N.B. our std::function
doesn't support construction with an allocator yet, any allocations it needs to do will be done using new
.
在回应埃米尔的评论前pressing避免了的std ::功能
持有一个成员函数指针和对象堆分配的欲望,这里有一个小黑客这样做(但你没有听到我的心声; - )
In response to Emile's comment expressing a desire to avoid a heap allocation for a std::function
which 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 ;-)
struct A {
int i = 0;
int foo() const { return 0; }
};
struct InvokeA
{
int operator()() const { return a->foo(); }
A* a;
};
namespace std
{
template<> struct __is_location_invariant<InvokeA>
{ static const bool value = true; };
}
int main()
{
A a;
InvokeA inv{ &a };
std::function<int()> f2(inv);
return f2();
}
诀窍是, InvokeA
是足够小,适合在函数的
小物体缓冲,而特质专业化说,它是安全的存储在那里,因此函数
直接持有该对象的副本,而不是在堆上。这就要求 A
只要它仍然存在,但无论如何都会是这样坚持的指针,如果函数
的目标是绑定。(安培; A :: foo,那么和放大器;一)
The trick is that InvokeA
is small enough to fit in the function
's small object buffer, and the trait specialization says it's safe to store in there, so the function
holds a copy of that object directly, not on the heap. This requires a
to persist as long as the pointer to it persists, but that would be the case anyway if the function
's target was bind(&A::foo, &a)
.
这篇关于有快速代理背后的思想(等人)被用于优化的std ::功能?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!