gpt4 book ai didi

c++ - 使用 asio::async_read 时接收之间的延迟

转载 作者:行者123 更新时间:2023-12-04 08:04:27 24 4
gpt4 key购买 nike

我正在使用 Boost/ASIO 编写通过 TCP/IP 通信的 C++ 服务器和随附的客户端应用程序。我看到连续接收之间的延迟导致服务器和客户端之间的吞吐量低于预期。两边的代码大致看起来像

class MyStream
{
...

void doStuff()
{
asio::async_read(socket, buffer, &bind(MyStream::readCallback, this, _1, _2)); // get some bytes
}

void readCallback(const error_code& err, size_t bytes_transferred)
{
processData(bytes_transferred); // maybe write some data back

asio::async_read(socket, buffer, &bind(MyStream::readCallback, this, _1, _2)); // get some additional bytes
}

...
};
服务器和客户端之间的消息传递非常慢,每秒来回传递 20-30 条消息。我在本地机器上进行测试,使用非常小的消息。
使用 ASIO 编译器标志 -DASIO_ENABLE_HANDLER_TRACKING我观察到一些接收之间的延迟始终约为 40 毫秒。
...
@asio|1613871309.603585|>22|ec=asio.system:0,bytes_transferred=30
@asio|1613871309.603688|22^34|in 'ssl::stream<>::async_read_some' ([redacted]/asio/include/asio/ssl/detail/io.hpp:167)
@asio|1613871309.603688|22*34|socket@0x7fdebc013f80.async_receive
@asio|1613871309.603703|.34|non_blocking_recv,ec=asio.system:11,bytes_transferred=0
@asio|1613871309.603725|<22|
@asio|1613871309.643974|.34|non_blocking_recv,ec=asio.system:0,bytes_transferred=248
@asio|1613871309.644013|>34|ec=asio.system:0,bytes_transferred=248
...
什么可能导致这 40 毫秒的延迟?

最佳答案

问题是消息非常小(几个字节或更少)并且被写入多个部分。这种模式,在配置了 Nagle 算法和延迟 ACK 的 TCP 连接上,导致单独发送之间的延迟,其中系统在发送更多数据之前等待 ACK,但存在 ACK 延迟(我的系统默认为 40 毫秒)。
编辑1:
正如大卫施瓦茨在评论中提到的 解决方案是聚合出站数据 .
另外,可以通过设置 TCP_NODELAY 选项来做一种解决方法,该选项禁用 Nagle 算法。

socket.set_option(asio::ip::tcp::no_delay(true));
还有一个 TCP_QUICKACK 标志,但来自 docs :

This flag is not permanent, it only enables a switch to or from quickack mode. Subsequent operation of the TCP protocol will once again enter/leave quickack mode depending on internal protocol processing and factors such as delayed ack timeouts occurring and data transfer. This option should not be used in code intended to be portable.


编辑2:为了后代-我修改了代码,一次使用 no_delay 选项,一次通过更改逻辑以在消息接收后执行分散-收集写入+快速确认(我使用的协议(protocol)没有应用程序-水平确认)。仅使用 no_delay,吞吐量从 ~30 msg/s 变为 ~300 msg/s。只有分散-收集写入 + 快速确认,吞吐量约为 1000 msg/s。这是针对我的特定用例的,但我希望这能让您了解什么对我最有效。
编辑 3:在将 TCP_NODELAY 与 scatter-gather 写入相结合后,我实现了最佳吞吐量,比 scatter-gather 和快速确认快 15%(结果证明这是一个非常慢的系统调用)

关于c++ - 使用 asio::async_read 时接收之间的延迟,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66298684/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com