使用 boost::asio::ip::tcp::iostream 的低带宽性能

2024-03-08

我写了一个小测试程序,使用boost::asio::ip::tcp::iostream传输约 38 MiB 的数据:

#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/asio.hpp>
#include <boost/serialization/export.hpp>
#include <boost/serialization/shared_ptr.hpp>
#include <boost/serialization/vector.hpp>
#include <chrono>
#include <iostream>
#include <sstream>
#include <string>
#include <thread>

using namespace std;

class Message {
public:
    Message() {
    }

    virtual ~Message() {
    }

    string text;
    std::vector<int> bigLoad;

private:
    friend class boost::serialization::access;

    template <class Archive>
    void serialize(Archive &ar, const unsigned int version) {
        ar &text;
        ar &bigLoad;
    }
};

BOOST_CLASS_EXPORT(Message)

void runClient() {
    // Give server time to startup
    this_thread::sleep_for(chrono::milliseconds(3000));

    boost::asio::ip::tcp::iostream stream("127.0.0.1", "3000");
    // const boost::asio::ip::tcp::no_delay option(true);
    // stream.rdbuf()->set_option(option);

    Message message;

    stringstream ss;
    ss << "Hello World!";
    message.text = ss.str();

    int items = 10000000;
    int size = sizeof(int) * items;

    std::cout << "Size in Byte = " << size << endl;
    std::cout << "Size in KiB = " << size / 1024 << endl;
    std::cout << "Size in MiB = " << size / 1024 / 1024 << endl;

    for (int i = 0; i < items; i++)
        message.bigLoad.push_back(i);

    boost::archive::text_oarchive archive(stream);

    cout << "Client start to send message" << endl;
    try {
        archive << message;
    } catch (std::exception &ex) {
        cout << ex.what() << endl;
    }
    cout << "Client send message" << endl;

    stream.close();
    cout << "Client shutdown" << endl;
}

void handleIncommingClientConnection(boost::asio::ip::tcp::acceptor &acceptor) {
    boost::asio::ip::tcp::iostream stream;
    // const boost::asio::ip::tcp::no_delay option(true);
    // stream.rdbuf()->set_option(option);

    acceptor.accept(*stream.rdbuf());

    boost::archive::text_iarchive archive(stream);

    while (true) {
        try {
            Message message;
            archive >> message;
            cout << message.text << endl;
        } catch (std::exception &ex) {
            cout << ex.what() << endl;

            if (stream.eof()) {
                cout << "eof" << endl;
                stream.close();
                cout << "Server: shutdown client handling..." << endl;
                break;
            } else
                throw ex;
        }
    }
}

void runServer() {
    boost::asio::io_service ios;
    boost::asio::ip::tcp::endpoint endpoint = boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), 3000);
    boost::asio::ip::tcp::acceptor acceptor(ios, endpoint);

    handleIncommingClientConnection(acceptor);
}

template <typename TimeT = std::chrono::milliseconds>
struct measure {
    template <typename F, typename... Args>
    static typename TimeT::rep execution(F &&func, Args &&... args) {
        auto start = std::chrono::steady_clock::now();
        std::forward<decltype(func)>(func)(std::forward<Args>(args)...);
        auto duration = std::chrono::duration_cast<TimeT>(std::chrono::steady_clock::now() - start);
        return duration.count();
    }
};

void doIt() {
    thread clientThread(runClient);
    thread serverThread(runServer);

    clientThread.join();
    serverThread.join();
}

int main(int argc, char **argv) {
    std::cout << measure<std::chrono::seconds>::execution(doIt) << std::endl;

    return 0;
}

程序在发布模式下的输出如下所示:

Size in Byte = 40000000
Size in KiB = 39062
Size in MiB = 38
Client start to send message
Client send message
Client shutdown
Hello World!
input stream error
eof
Server: shutdown client handling...
148

传输 38 MB 需要 148 秒(超过 2 分钟)。我可以将数据复制到 U 盘并手动移交,速度比boost::asio does.

有什么办法可以提高带宽性能吗?


您的时间可能浪费在与文本的序列化上。

对我来说,放入二进制存档确实将速度从 80Mbit/s 提高到 872MBit/s:

Client start to send message
Client send message
Client shutdown
Received: Hello World!
3

总时间(以秒为单位)减少到 3 秒,这恰好是初始睡眠:)

Proof Of Concept Live On Coliru http://coliru.stacked-crooked.com/a/137017448a238a71

#include <boost/archive/binary_iarchive.hpp>
#include <boost/archive/binary_oarchive.hpp>
#include <boost/archive/text_iarchive.hpp>
#include <boost/archive/text_oarchive.hpp>
#include <boost/asio.hpp>
#include <boost/serialization/export.hpp>
#include <boost/serialization/shared_ptr.hpp>
#include <boost/serialization/vector.hpp>
#include <chrono>
#include <iostream>
#include <sstream>
#include <string>
#include <thread>

using namespace std;

class Message {
  public:
    Message() {}

    virtual ~Message() {}

    string text;
    std::vector<int> bigLoad;

  private:
    friend class boost::serialization::access;

    template <class Archive> void serialize(Archive &ar, const unsigned int /*version*/) {
        ar & text & bigLoad;
    }
};

BOOST_CLASS_EXPORT(Message)

void runClient() {
    // Give server time to startup
    this_thread::sleep_for(chrono::seconds(1));

    boost::asio::ip::tcp::iostream stream("127.0.0.1", "3000");
    const boost::asio::ip::tcp::no_delay option(false);
    stream.rdbuf()->set_option(option);

    Message message;

    stringstream ss;
    ss << "Hello World!";
    message.text = ss.str();

    int items = 8 << 20;

    for (int i = 0; i < items; i++)
        message.bigLoad.push_back(i);

    boost::archive::binary_oarchive archive(stream);

    cout << "Client start to send message" << endl;
    try {
        archive << message;
    } catch (std::exception &ex) {
        cout << ex.what() << endl;
    }
    cout << "Client send message" << endl;

    stream.close();
    cout << "Client shutdown" << endl;
}

void handleIncommingClientConnection(boost::asio::ip::tcp::acceptor &acceptor) {
    boost::asio::ip::tcp::iostream stream;
    // const boost::asio::ip::tcp::no_delay option(false);
    // stream.rdbuf()->set_option(option);

    acceptor.accept(*stream.rdbuf());

    boost::archive::binary_iarchive archive(stream);

    {
        try {
            Message message;
            archive >> message;
            cout << "Received: " << message.text << endl;
        } catch (std::exception &ex) {
            cout << ex.what() << endl;

            if (stream.eof()) {
                cout << "eof" << endl;
                stream.close();
                cout << "Server: shutdown client handling..." << endl;
                return;
            } else
                throw;
        }
    }
}

void runServer() {
    using namespace boost::asio;
    using ip::tcp;

    io_service ios;
    tcp::endpoint endpoint = tcp::endpoint(tcp::v4(), 3000);
    tcp::acceptor acceptor(ios, endpoint);

    handleIncommingClientConnection(acceptor);
}

template <typename TimeT = std::chrono::milliseconds> struct measure {
    template <typename F, typename... Args> static typename TimeT::rep execution(F &&func, Args &&... args) {
        auto start = std::chrono::steady_clock::now();
        std::forward<decltype(func)>(func)(std::forward<Args>(args)...);
        auto duration = std::chrono::duration_cast<TimeT>(std::chrono::steady_clock::now() - start);
        return duration.count();
    }
};

void doIt() {
    thread clientThread(runClient);
    thread serverThread(runServer);

    clientThread.join();
    serverThread.join();
}

int main() { std::cout << measure<std::chrono::seconds>::execution(doIt) << std::endl; }

Caution:

这里“丢失”了一件事,旧版本的代码也没有真正支持这一点:直接接收多个档案。

您可能想要设备某种成帧协议。参见例如

  • Boost 序列化二进制存档给出不正确的输出 https://stackoverflow.com/questions/26556145/boost-serialization-binary-archive-giving-incorrect-output/26568212#26568212
  • 输出比多态文本档案更多的东西 https://stackoverflow.com/questions/27422557/outputting-more-things-than-a-polymorphic-text-archive/27424381#27424381
  • 流不是档案(http://www.boost.org/doc/libs/1_51_0/libs/serialization/doc/ http://www.boost.org/doc/libs/1_51_0/libs/serialization/doc/)

我在这里发表了一些“Boost Serialization 的开销”帖子:

  • 如何使用 boost 库对自定义库进行性能测试 https://stackoverflow.com/questions/23571355/how-to-do-performance-test-using-the-boost-library-for-a-custom-library/23572674#23572674
  • Boost C++ 序列化开销 https://stackoverflow.com/questions/22459726/boost-c-serialization-overhead/22464553#22464553
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 boost::asio::ip::tcp::iostream 的低带宽性能 的相关文章

  • 如何检查图像对象与资源中的图像对象是否相同?

    所以我试图创建一个简单的程序 只需在单击图片框中更改图片即可 我目前只使用两张图片 所以我的图片框单击事件函数的代码 看起来像这样 private void pictureBox1 Click object sender EventArgs
  • 如何验证文件名称在 Windows 中是否有效?

    是否有一个 Windows API 函数可以将字符串值传递给该函数 该函数将返回一个指示文件名是否有效的值 我需要验证文件名是否有效 并且我正在寻找一种简单的方法来完成此操作 而无需重新发明轮子 我正在直接使用 C 但针对的是 Win32
  • 当我使用“control-c”关闭发送对等方的套接字时,为什么接收对等方的套接字不断接收“”

    我是套接字编程的新手 我知道使用 control c 关闭套接字是一个坏习惯 但是为什么在我使用 control c 关闭发送进程后 接收方上的套接字不断接收 在 control c 退出进程后 发送方的套接字不应该关闭吗 谢谢 我知道使用
  • 如何使用GDB修改内存内容?

    我知道我们可以使用几个命令来访问和读取内存 例如 print p x 但是如何更改任何特定位置的内存内容 在 GDB 中调试时 最简单的是设置程序变量 参见GDB 分配 http sourceware org gdb current onl
  • pthread_cond_timedwait() 和 pthread_cond_broadcast() 解释

    因此 我在堆栈溢出和其他资源上进行了大量搜索 但我无法理解有关上述函数的一些内容 具体来说 1 当pthread cond timedwait 因为定时器值用完而返回时 它如何自动重新获取互斥锁 互斥锁可能被锁定在其他地方 例如 在生产者
  • C++ 子字符串返回错误结果

    我有这个字符串 std string date 20121020 我正在做 std cout lt lt Date lt lt date lt lt n std cout lt lt Year lt lt date substr 0 4 l
  • WPF 中的调度程序和异步等待

    我正在尝试学习 WPF C 中的异步编程 但我陷入了异步编程和使用调度程序的困境 它们是不同的还是在相同的场景中使用 我愿意简短地回答这个问题 以免含糊不清 因为我知道我混淆了 WPF 中的概念和函数 但还不足以在功能上正确使用它 我在这里
  • 如果使用 SingleOrDefault() 并在数字列表中搜索不在列表中的数字,如何返回 null?

    使用查询正数列表时SingleOrDefault 当在列表中找不到数字时 如何返回 null 或像 1 这样的自定义值 而不是类型的默认值 在本例中为 0 你可以使用 var first theIntegers Cast
  • vector 超出范围后不清除内存

    我遇到了以下问题 我不确定我是否错了或者它是一个非常奇怪的错误 我填充了一个巨大的字符串数组 并希望在某个点将其清除 这是一个最小的例子 include
  • 从路径中获取文件夹名称

    我有一些路c server folderName1 another name something another folder 我如何从那里提取最后一个文件夹名称 我尝试了几件事 但没有成功 我只是不想寻找最后的 然后就去休息了 Thank
  • for循环中计数器变量的范围是多少?

    我在 Visual Studio 2008 中收到以下错误 Error 1 A local variable named i cannot be declared in this scope because it would give a
  • 如何将单个 char 转换为 int [重复]

    这个问题在这里已经有答案了 我有一串数字 例如 123456789 我需要提取它们中的每一个以在计算中使用它们 我当然可以通过索引访问每个字符 但是如何将其转换为 int 我研究过 atoi 但它需要一个字符串作为参数 因此 我必须将每个字
  • 实体框架 4 DB 优先依赖注入?

    我更喜欢创建自己的数据库 设置索引 唯一约束等 使用 edmx 实体框架设计器 从数据库生成域模型是轻而易举的事 现在我有兴趣使用依赖注入来设置一些存储库 我查看了 StackOverflow 上的一些文章和帖子 似乎重点关注代码优先方法
  • C++ fmt 库,仅使用格式说明符格式化单个参数

    使用 C fmt 库 并给定一个裸格式说明符 有没有办法使用它来格式化单个参数 example std string str magic format 2f 1 23 current method template
  • Validation.ErrorTemplate 的 Wpf 动态资源查找

    在我的 App xaml 中 我定义了一个资源Validation ErrorTemplate 这取决于动态BorderBrush资源 我打算定义独特的BorderBrush在我拥有的每个窗口以及窗口内的不同块内
  • x86 上未对齐的指针

    有人可以提供一个示例 将指针从一种类型转换为另一种类型由于未对齐而失败吗 在评论中这个答案 https stackoverflow com questions 544928 reading integer size bytes from a
  • 如何使用 std::string 将所有出现的一个字符替换为两个字符?

    有没有一种简单的方法来替换所有出现的 in a std string with 转义 a 中的所有斜杠std string 完成此操作的最简单方法可能是boost字符串算法库 http www boost org doc libs 1 46
  • ASP.NET MVC 6 (ASP.NET 5) 中的 Application_PreSendRequestHeaders 和 Application_BeginRequest

    如何在 ASP NET 5 MVC6 中使用这些方法 在 MVC5 中 我在 Global asax 中使用了它 现在呢 也许是入门班 protected void Application PreSendRequestHeaders obj
  • 限制C#中的并行线程数

    我正在编写一个 C 程序来生成并通过 FTP 上传 50 万个文件 我想并行处理4个文件 因为机器有4个核心 文件生成需要更长的时间 是否可以将以下 Powershell 示例转换为 C 或者是否有更好的框架 例如 C 中的 Actor 框
  • 使用按位运算符相乘

    我想知道如何使用按位运算符将一系列二进制位相乘 但是 我有兴趣这样做来查找二进制值的十进制小数值 这是我正在尝试做的一个例子 假设 1010010 我想使用每个单独的位 以便将其计算为 1 2 1 0 2 2 1 2 3 0 2 4 虽然我

随机推荐

  • 在 Backbone.js 中实现 Backbone.Subset.js 以从父集合中过滤模型

    In 这个 stackoverflow 帖子 https stackoverflow com questions 6865174 backbone js correct way of filter collection data and d
  • 如何获取 ntile() 的间隔

    我试图弄清楚是否有一种方法可以获取用于何时的间隔ntile 用来 我有一个样本 我想将其用作获取较大样本的百分位值的基础 并且我希望找到一种方法来获取使用时的间隔值ntile 对此的任何启发将不胜感激 我真的很想把这个作为评论 但我仍然无法
  • 手动删除 anaconda python 中 pkgs 文件夹中的所有文件是否安全?

    我运行这个命令来释放 anaconda 上的磁盘空间 conda clean all 但是 仍然有一些大文件残留在pkgsanaconda python 中的文件夹 手动删除其中的所有文件是否安全pkgs文件夹 有破坏我的 anaconda
  • Invoke-Restmethod:如何获取返回码?

    有没有办法在调用时将返回码存储在某处Invoke RestMethod在 PowerShell 中 我的代码如下所示 url http www dictionaryapi com api v1 references collegiate x
  • 如何从字符串中获取size_t?

    我需要从用户输入中获取数组大小 对我来说 将输入存储为很自然size t 但是正在寻找合适的strto 功能我找不到 我刚用过strtoull since unsigned long long保证至少是 64 位 而且我无论如何都使用 C9
  • 可变值和不可变值重定义有什么区别?

    我读到 F 中的值是不可变的 然而 我也遇到了重新定义价值定义的概念 它掩盖了以前的定义 这与可变值有何不同 我问这不仅是一个理论构造 而且还询问是否有关于何时使用可变值以及何时重新定义表达式的建议 或者如果有人可以指出后者不是惯用的 f
  • 如何让 GNU Unifont 或 Free Mono 在 gvim windows 上运行?

    我正在尝试在 Windows 7 上的 gvim 中获得对符文字符的支持 我的 Fonts 目录中安装了 Free Mono 和 GNU Unifont 字体 都支持此范围 但它们没有出现在字体菜单中 gvim 给出了我收到以下行的无效字体
  • ASP.NET MVC 4 引用单父实体的多个外键

    我正在尝试开发一个 ASP NET MVC 4 应用程序 可以根据玩家的进攻 防守和助攻技能对他们进行评级 进攻 防守和助攻是球员表上的外键 引用相同的查找表 评分 我有以下父实体 public class Rating public in
  • 为什么 tzset() 在 Mac OS X 上 fork 后速度变慢了?

    Calling tzset fork之后显得很慢 如果我第一次打电话 我只会看到缓慢的情况tzset 在 fork 之前在父进程中 我的TZ环境变量未设置 我dtruss我的测试程序显示子进程读取 etc localtime对于每一个tzs
  • 如何将按钮对齐到屏幕中间?

    我正在尝试在屏幕中间放置 2 个按钮 然而 这些按钮与我现在拥有的代码重叠 实际上我并没有使用那么多 CSS 所以这可能是一个新手问题 这是我的html wrapper text align center button position a
  • 使用 AVMutableComposition 缝合(合并)视频时修复方向

    TLDR 查看编辑 我正在 Swift 中创建一个测试应用程序 我想使用以下命令将应用程序文档目录中的多个视频拼接在一起AVMutableComposition 我在某种程度上成功地做到了这一点 我的所有视频都拼 接在一起 并且所有内容都显
  • HTTP 请求损坏

    在接收大量流量的网站上 一小部分请求是这样的 http cheezburger com ScriptResource axd d zaVpgH63ePt90pn br br p a src ScriptResource axd d zaVp
  • TFS 与 JIRA/Bamboo/SVN [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 如何在 us-central1 以外的网络区域使用 httpsCallable

    我部署了一个云函数 如下所示 export const publishVersion functions region europe west2 https onCall async data context gt 然后在我的网络客户端中
  • Golang - ToUpper() 在单个字节上?

    我有一个 byte b 我想选择一个字节 b pos 并将其更改为大写 然后小写 bytestype 有一个方法叫做ToUpper 我如何将其用于单个字节 Calling ToUpper在单字节上 OneOfOne 给出了最有效的 调用数千
  • 柯里化有什么好处?

    我认为我不太理解柯里化 因为我看不到它可以提供任何巨大的好处 也许有人可以用一个例子来启发我 证明它为什么如此有用 它真的有好处和应用吗 还是只是一个被过度重视的概念 两者之间有细微差别currying and 部分应用 尽管它们密切相关
  • BigQuery 分区表在 _PARTITIONTIME 上联接

    有两个分区表 都带有伪列 PARTITIONTIME 我想在 PARTITIONTIME 上加入它们 然后我想使用 PARTITIONTIME 过滤器查询结果表 但我注意到该过滤器仅传播到 JOIN 语句的第一个表 下面是一个例子 WITH
  • 如何在 Sublime Text 2 中解析来自 TypeScript 的错误消息?

    我正在尝试为 TypeScript 设置 Sublime Text 2 构建系统 我已按照我找到的指示进行操作here https stackoverflow com questions 12779631 how to configure
  • 问题 如何使 C# 的 VS IDE 设计器失效/刷新?

    I have 定制表格继承自Form它实现了一个名为的布尔属性Prop 我将使用的表单将继承自定制表格 此属性将对表单进行一些绘制和更改 如果已启用 但是 这并没有按预期工作 设计的 VS IDE 没有刷新以显示更改 但是 如果我按 Ctr
  • 使用 boost::asio::ip::tcp::iostream 的低带宽性能

    我写了一个小测试程序 使用boost asio ip tcp iostream传输约 38 MiB 的数据 include