有快速代理背后的思想(等人)被用于优化的std ::功能? [英] Have the ideas behind the Fast Delegate (et al) been used to optimize std::function?

查看:174
本文介绍了有快速代理背后的思想(等人)被用于优化的std ::功能?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有一直为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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆