zeromq具有高延迟



我正在尝试使用PUB/SUB模式运行一个带有zeromq的本地低延迟控制循环。

然而,在不同的标准Ubuntu LTS安装(从16。xx - 20.xx)和不同的pc都运行默认内核,我经历了相当高的延迟,从0.3ms到>1 ms .

我的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)

这是一个简单的PHP redis脚本,默认安装在本地redis-server上,比我能实现的任何c++/PHP/node zeromq实现延迟(<100us - 400us)低几倍:

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

您测量的延迟是从调用发行者中的gettimeofday()到订阅者中的gettimeofday()。这将因两台PC的rtc之间的差异而有所不同,即使与ntpd等内容同步,也不会完全对齐。如果订阅者将消息反射回另一个套接字,则发布者将能够测量往返时间。

话虽如此,无论如何,我不期望延迟比您通过以太网测量的任何数据交换的延迟更好。流量太过于受网络和个人电脑中发生的其他事情的支配。如果你需要保证一台PC会在100秒内对另一台PC上的事件做出反应,那么以太网/TCPIP/Linux/PC可能是错误的技术。

例如,如果你的PC的CPU决定改变电压/时钟模式,整个PC可以停止的方式,方式超过100us,而这正在发生。我见过一些至强系统在发生这种CPU模式变化时整机暂停300ms。这样的事情超出了操作系统的控制能力——它在固件层。

最新更新