【问题标题】:Does boost::bind cause overhead?boost::bind 会导致开销吗?
【发布时间】:2011-08-19 04:38:03
【问题描述】:

我目前正在研究网络软件。它有一个主类server,它显然代表了一个服务器实例。

server 实例可以发送请求,并通过回调通知用户响应。

代码如下:

class server
{
  public:
    typedef boost::function<void (int duration)> callback_func;

    void send_request(endpoint& ep, callback_func cb);
};

现在假设,作为用户,我想通过回调了解调用它的实例,我可以执行以下操作:

void mycallback(const server& sv, int duration) { ... }

server sv;
sv.send_request("localhost", boost::bind(&mycallback, boost::ref(sv), _1));

但我想知道:这样做有什么开销吗?对mycallback 的调用会比使用“常规”调用慢吗?

谢谢。

脚注:我当然可以将我的typedef 更改为:typedef boost::function&lt;void (const server&amp; sv, int duration)&gt; callback_func;,如果boost::bind 造成任何重大开销,那可能就是我最终要做的。我只是想知道使用boost::bind 意味着什么成本。

【问题讨论】:

    标签: c++ boost bind overhead


    【解决方案1】:

    当然会导致开销。它的作用是创建一个存储绑定参数的函子,并具有一个operator(),您可以使用剩余的参数调用它。现在,这很重要吗?我不知道,因为那只是一个词。发出 1000 万个请求并对其进行衡量。您是唯一可以判断此开销对您是否重要的​​人。

    另外,我也遇到了类似的问题。因为我真的不需要委托,所以我可以摆脱函数指针。但我发现了一个有趣的benchmark,它还提到了一些替代实现,它们的性能都比boost::function 更好。这是以可移植性为代价的,在某些情况下,实现中会出现丑陋、非标准的 hack(但作为回报,性能非常好)。

    【讨论】:

    • Boost v1.36.0(2008 年发布)为 boost::function 引入了一个小对象优化,导致引用的基准测试结果(从 2007 年开始)无效。
    • 这是一个重要的说明,谢谢。您是否知道最近的基准?
    【解决方案2】:

    boost::bind 生成一个函数对象,如果将其用作函数模板的参数,则可以对其进行优化,但 boost::function 会阻止这种优化,就像将指针传递给函数会阻止其内联一样。 boost::function 本身不需要引入比虚函数 all 或通过函数指针调用更多的开销。

    PS。我同意 Tamás Szelei 的观点:提出 1000 万个请求并对其进行衡量。

    【讨论】:

    • 即使作为参数传递给模板函数,这也取决于您的编译器:前几天我正在测试一个带有迭代器的直接循环与带有 boost::bind 的 std::for_each:gcc 4.5 优化它使用几乎相同的代码,使用 gcc 4.1 和 4.2 它产生了相当大的膨胀。
    • boost::function 对不是非常小的对象使用堆分配。所以你最好检查你的绑定对象是否低于限制。
    【解决方案3】:

    与普通函数调用相比,您需要为函数调用支付两次间接费用,这类似于(非去虚拟化)虚函数调用的开销。

    第一个间接是由于 boost::function 中发生的类型擦除(这是boost::function 文档中的documented)。这个不能真正优化,你也会有一个裸函数指针同样的惩罚。

    第二种间接来自通过函数指针调用mycallback 函数。一个非常优化的编译器可以解决这个问题并优化它,但一个普通的编译器不会。如果将mycallback 转换为函数对象,则可以摆脱这种间接(在所有编译器中):

    代替

    void mycallback( .1. ) { .2. }
    

    你会的

    struct mycallback {
        void operator()( .1. ) const { .2. }
    };
    

    【讨论】:

      【解决方案4】:

      注意 boost::bind 会导致仿函数的副本。这可能非常重要。对于我的操作系统来说,新闻和删除非常昂贵。请参阅有关 ref() 和 cref() 的 boost::bind 文档。我相信成员函数也会导致仿函数副本,但没有相关文档。

      【讨论】:

      • 我错了。 boost::bind 确实制作仿函数的副本,但它确实制作了参数的副本。对于不复制参数的版本,请参阅关于 ref() 和 cref() 的 boost::bind 文档。
      猜你喜欢
      • 2021-11-30
      • 2023-04-01
      • 2012-05-18
      • 1970-01-01
      • 2012-01-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-15
      相关资源
      最近更新 更多