C++ asio缓冲区深度拷贝

C++ asio缓冲区深度拷贝,c++,performance,boost,boost-asio,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 d

我发现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) {
}
类MyData{
std::矢量数据;
};
无效处理程序(请求请求){
MyData d;
异步写入(缓冲区(数据)…);
}//oops,d已销毁,但实际写入尚未执行
//这是可以的,但如果数据非常小,则性能会很糟糕
无效处理程序(请求请求){
共享(新MyData());
异步写入(缓冲区(d->数据)…绑定(&X::句柄写入,this,d);
}
无效句柄写入(共享){
}
为什么asio没有提供一个可以进行深度复制的缓冲区?这将节省复制时间,但对于发送大量小数据的应用程序来说,性能应该更差


在其文档中,connection对象有一个成员用来保存数据,但对于大多数应用程序来说,只有一个数据成员是不够的。当应用程序可以随时写入数据时,需要使用队列(不喜欢HTTP等半双工协议)否则数据可能会被下一次写入覆盖。因此,如果队列是queue,则仍然需要调用new;如果队列是queue,则仍然需要复制。ASIO不提供此类缓冲区类,但可以编写自己的缓冲区类。该示例还提供了此类的实现


为了提高性能,可以组织一个池,例如库使用的池。

Boost。Asio的缓冲区类型不要求实际内存需要分配到哪里。它只要求它所代表的内存是连续的,如果不是连续的,则需要缓冲区序列待使用

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

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

在分析和识别分配和副本是瓶颈之后,然后考虑采用设计来解决特定问题的技术:

  • 将允许重新使用内存,而不是将内存释放回空闲存储区
  • 在某些情况下,引用计数缓冲区可以消除执行深度副本的需要。请考虑使用官方示例或<代码> Boo/STD::SyrdYPPTR < /代码>。这些甚至可以通过使用自定义删除器由池管理的类型使用。
  • 对于唯一所有权,
    std::unique_ptr
    和/或move语义也可以删除不必要的深度副本

您不必为缓冲区使用动态分配的数据,您只需确保传递到缓冲区的数据的生存期足够长,以便在执行处理程序之前它不会超出范围。在这种情况下,如果dest仍然在堆栈上分配数据,则buffer\u copy是无用的。@jean有些情况下CTION是无用的,但这并不意味着函数一直都是无用的。我使用了
buffer\u copy
将调用者提供的内存深度复制到基于堆栈的内存,允许调用者在我执行同步操作时重用内存。是的……我不得不说asio设计的目标更强调多用途,但有点损失方便的