【发布时间】:2021-07-31 00:27:25
【问题描述】:
我正在尝试使用 PUB / SUB 模式使用 zeromq 运行本地低延迟控制循环。
但是,在不同的标准 Ubuntu LTS 安装(从 16.xx 到 20.xx)和不同的 PC 上都运行默认内核,我遇到了 0.3ms 到 > 1ms 之间的相当高的延迟。
我的 zeromq 版本是 4.3.2,cppzmq 版本是 4.2(但我在节点和 PHP 绑定方面也遇到了同样的问题)。
示例输出:
TOPIC RECV_US SEND_US
[datawriter_CPLUSPLUS] 1627690147280.142090 1627690147279.663086
[datawriter_CPLUSPLUS] 1627690147380.287109 1627690147379.824951
[datawriter_CPLUSPLUS] 1627690147480.525879 1627690147480.058105
[datawriter_CPLUSPLUS] 1627690147580.789062 1627690147580.251953
[datawriter_CPLUSPLUS] 1627690147680.885010 1627690147680.388916
[datawriter_CPLUSPLUS] 1627690147781.051025 1627690147780.531982
[datawriter_CPLUSPLUS] 1627690147881.116943 1627690147880.676025
[datawriter_CPLUSPLUS] 1627690147981.365967 1627690147980.818115
[datawriter_CPLUSPLUS] 1627690148081.508057 1627690148080.954102
[datawriter_CPLUSPLUS] 1627690148181.571045 1627690148181.091064
[datawriter_CPLUSPLUS] 1627690148281.747070 1627690148281.235107
[datawriter_CPLUSPLUS] 1627690148381.841064 1627690148381.378906
[datawriter_CPLUSPLUS] 1627690148482.018066 1627690148481.541992
[datawriter_CPLUSPLUS] 1627690148582.245117 1627690148581.775879
[datawriter_CPLUSPLUS] 1627690148682.593018 1627690148681.972900
输出来自运行以下我为调试而编写的简单发布者和订阅者程序:
出版商
#include "zhelpers.hpp"
#include <future>
#include <iostream>
#include <string>
int main()
{
zmq::context_t ctx;
zmq::socket_t publisher(ctx, zmq::socket_type::pub);
publisher.bind("tcp://127.0.0.1:3000");
struct timeval time;
while (true) {
gettimeofday(&time, NULL);
unsigned long long microsec = ((unsigned long long)time.tv_sec * 1000000) + time.tv_usec;
std::string string = std::to_string(microsec/1E3);
zmq::message_t message(string.size());
std::memcpy (message.data(), string.data(), string.size());
publisher.send(zmq::str_buffer("datawriter_CPLUSPLUS"), zmq::send_flags::sndmore);
publisher.send(message);
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
}
订阅者
#include "zhelpers.hpp"
#include <future>
#include <iostream>
#include <string>
int main () {
zmq::context_t context(1);
zmq::socket_t subscriber (context, ZMQ_SUB);
subscriber.connect("tcp://localhost:3000");
subscriber.setsockopt( ZMQ_SUBSCRIBE, "datalogger_CPLUSPLUS", 1);
struct timeval time;
while (1) {
std::string address = s_recv (subscriber);
std::string contents = s_recv (subscriber);
gettimeofday(&time, NULL);
unsigned long long microsec = ((unsigned long long)time.tv_sec * 1000000) + time.tv_usec;
std::string string = std::to_string(microsec/1E3);
std::cout << "[" << address << "] " << string << " " << contents << std::endl;
}
return 0;
}
我的目标延迟低于 100 微秒,而不是当前的 300 - 1300 微秒。 上面的延迟对我来说看起来非常高,如果这是我的 zeromq、实现或我的系统/内核配置的问题,我有点想不通。
添加
这是我机器的上下文切换时间,在不同的运行中非常一致:
./cpubench.sh
model name : AMD Ryzen 7 PRO 4750U with Radeon Graphics
1 physical CPUs, 8 cores/CPU, 2 hardware threads/core = 16 hw threads total
-- No CPU affinity --
10000000 system calls in 874207825ns (87.4ns/syscall)
2000000 process context switches in 4237346473ns (2118.7ns/ctxsw)
2000000 thread context switches in 4877734722ns (2438.9ns/ctxsw)
2000000 thread context switches in 318133810ns (159.1ns/ctxsw)
-- With CPU affinity --
10000000 system calls in 525663616ns (52.6ns/syscall)
2000000 process context switches in 2814706665ns (1407.4ns/ctxsw)
2000000 thread context switches in 2402846574ns (1201.4ns/ctxsw)
2000000 thread context switches in 407292570ns (203.6ns/ctxsw)
这是一个在默认安装本地 redis-server 上的简单 PHP redis 脚本,其延迟(
1627695114039.4 1627695114039.2
1627695114139.8 1627695114139.6
1627695114240.1 1627695114239.9
1627695114340.3 1627695114340.2
1627695114440.5 1627695114440.3
1627695114540.7 1627695114540.6
1627695114640.9 1627695114640.8
1627695114741.2 1627695114741.1
【问题讨论】:
-
桌面操作系统不是实时操作系统。尝试测量您的机器的任务上下文切换持续时间......我发现任务上下文切换通常比函数调用慢 3 或 4 个数量级。而且默认的 Linux 不是实时的。如果您的目标是 3 到 13 * 100(即已经比您的“需要”慢 2 个数量级),那么您可能选择了错误的系统。
-
谢谢,我添加了一个上下文切换基准,并与使用 PHP 脚本作为读取器和写入器的标准 redis 服务器安装进行了比较。
-
最简单的 1Gig 以太网的 Ping 时间超过 0.48 毫秒(我见过的最短时间)。鉴于这是可以通过网络执行的最简单/最快的往返事务,我怀疑 TCP(在 ZMTP 之上运行)对于单向传输的数据包可以击败一半,事实上你已经发现至少 0.3ms。有趣的是,前一段时间的传说是 100M 网络上的 ping 时间比 1Gig 网络上的要短。