asio缓冲区深拷贝

时间:2013-06-27 10:57:24

标签: c++ performance boost boost-asio

我发现asio缓冲区的引用语义不方便使用。它要求用户在堆中分配数据,但是对于小尺寸数据(例如,100字节),在堆栈上分配并复制几次(我认为使用asio时复制时间应小于3)将比调用一个新操作。 例如:

class MyData {
    std::vector<char> data;
};

void hander(Request req) {
    MyData d;
    async_write(buffer(d.data)...);
} // oops, d was destroyed, but the actual write have not execute

// this is ok, but awkward and poor performance if data is very small
void hander(Request req) {
    shared_ptr<MyData> d(new MyData());
    async_write(buffer(d->data)...bind(&X::handle_write, this, d);
}
void handle_write(shared_ptr<MyData> s) {
}

为什么asio没有提供可以进行深层复制的缓冲区?它会节省复制时间以提高性能,但对于应用程序发送大量小数据,性能应该更差

在其doc中,连接对象有一个用于保存数据的成员,但对于大多数应用程序,数据成员是不够的。当应用程序可以随时写入数据时,需要使用队列(不要像HTTP这样的半双工协议),否则下次写入可能会导致数据被覆盖。所以如果队列是Queue,那仍然需要调用new,如果队列是Queue,那还是需要复制

2 个答案:

答案 0 :(得分:3)

Boost.Asio的缓冲区类型对于需要分配实际内存的位置没有任何要求。它只需要它所代表的内存是连续的,当它不连续时,则需要使用缓冲区序列。

Boost.Asio提供buffer_copy,可用于从一个缓冲区或缓冲区序列到另一个缓冲区或缓冲区序列执行深层复制。纯粹的推测,但Asio可能不提供拥有底层内存的缓冲区,因为:

  • 内存使用特性因应用程序而异。如果使用良好的默认分配或所有权策略,则不明显。
  • boost::buffer()提供了一种从各种类型(原始内存,c-array,boost/std::arraystd::vectorstd::string)创建Boost.Asio缓冲区的便捷方法。其中一些类型已经提供了自定义分配的方法,以及执行深层复制的方法(复制构造函数,赋值,std::copy)。
  • Boost.Asio操作是根据缓冲区序列的概念/类型要求实现的,例如MutableBufferSequence,而不是实际类型,例如boost::asio::mutable_buffers。因此,只要满足类型要求,用户就可以自由使用自己的类型和内存管理。以下是reference counted buffer
  • 的官方示例

在分析并确定分配和副本是瓶颈之后,请考虑采用旨在解决特定问题的技术:

  • Memory Pools将允许重用内存,而不是将内存释放回免费商店。
  • 在某些情况下,引用计数缓冲区可能无需执行深层复制。请考虑使用官方示例或boost/std::shared_ptr。这些甚至可以由池通过使用自定义删除器管理的类型使用。
  • 对于唯一所有权,std::unique_ptr和/或move-semantics也可能删除不必要的深层副本。

答案 1 :(得分:0)

ASIO不提供这样的缓冲类,但编写自己的缓冲类是可行的。此外,Buffers示例还具有此类的实现。

为了提高性能,可以组织一个池,例如WebSocket++库使用its own message pool