【问题标题】:ZeroMQ - pub / sub latencyZeroMQ - 发布/订阅延迟
【发布时间】:2015-09-14 01:27:22
【问题描述】:

我正在研究 ZeroMQ,看看它是否适合软实时应用程序。我很高兴看到小型有效载荷的延迟在 30 微秒左右的范围内。但是在我的简单测试中,我得到了大约 300 微秒。

我有一个简单的发布者和订阅者,基本上是从网络上的示例复制而来,我通过 localhost 发送一个字节。

我已经和不同的sockopts 玩了大约两天,我正在三振出局。

任何帮助将不胜感激!

发布者发布者:

#include <iostream>
#include <zmq.hpp>
#include <unistd.h>

#include <sys/time.h>


int main()
{
    zmq::context_t context (1);
    zmq::socket_t publisher (context, ZMQ_PUB);
    publisher.bind("tcp://*:5556");

    struct timeval timeofday;
    zmq::message_t msg(1);
    while(true)
    {
        gettimeofday(&timeofday,NULL);
        publisher.send(msg);
        std::cout << timeofday.tv_sec << ", " << timeofday.tv_usec << std::endl;
        usleep(1000000);
    } 
}  

订阅者抄写员:

#include <iostream>
#include <zmq.hpp>
#include <sys/time.h>


int main()
{
    zmq::context_t context (1);
    zmq::socket_t subscriber (context, ZMQ_SUB);
    subscriber.connect("tcp://localhost:5556");
    subscriber.setsockopt(ZMQ_SUBSCRIBE, "", 0);

    struct timeval timeofday;
    zmq::message_t update;
    while(true)
    {
        subscriber.recv(&update);
        gettimeofday(&timeofday,NULL);
        std::cout << timeofday.tv_sec << ", " << timeofday.tv_usec << std::endl;
    }
}

【问题讨论】:

标签: c++ zeromq latency


【解决方案1】:

任务定义是真的吗?

说到 *-real-time 设计,架构能力验证比下面的实现本身更重要。

如果按原样获取源代码,则您的读数(理想情况下将与您的代码 sn-ps 一起发布,以对复制的 MCVE-retest 进行交叉验证)不会起到太大作用,因为数字无法区分在发送端循环器、发送端 zmq-data-acquisition/复制/调度/线级格式化/数据报调度和接收端从媒体卸载/复制/解码上花费了哪些部分(多少时间) /pattern-match/传播到接收缓冲区

如果对 ZeroMQ 内部结构感兴趣,可以参考与性能相关的优秀应用说明。

如果努力实现最小延迟设计,请执行以下操作:

  • 删除所有开销
    • 从提议的PUB/SUB频道替换所有tcp-header处理
    • 避免处理过程中的所有非主要逻辑开销(在 subscribe-side 上花费时间毫无意义(当然,较新版本的 ZMQ 已移至 publisher-侧过滤,但想法很清楚)在所选原型处理中编码的模式匹配(使用 ZMQ_PAIR 避免任何此类,独立于传输类) - 如果它打算阻止某些东西,然后相应地更改信令套接字布局,以便原则上避免阻塞(这应该是一个实时系统,正如你上面所说的)
    • 在目标多核/多核硬件架构中尽可能应用“延迟屏蔽”,以便从您的硬件/工具功能中榨取最后一滴空闲时间......通过更多实验设置进行基准测试I/O 线程的帮助 zmq::context_t context( N );,其中 N > 1

缺少目标:

正如一个多世纪前的爱丽丝梦游仙境所说,只要没有明确的目标,任何道路都会通向目标。

有一个软实时的野心,不存在规定最大允许端到端延迟并由此得出传输层延迟约束的问题。

如果没有这样做,30 us、300 us 甚至 3 ms 本身就没有任何意义,所以没有人可以决定这些数字对于某些子系统是否“足够”。

合理的下一步:

  • 定义实时稳定性范围...如果用于实时控制
  • 定义实时设计约束...用于信号/数据采集、处理任务、自诊断和控制服务
  • 避免任何阻塞、设计明智和验证/证明在所有可能的实际操作情况下都不会出现阻塞[正式的证明方法已准备好执行此类任务](没有人愿意看到@ 987654326@ [等待数据] 在您的下一次喷气式飞机着陆或最后一件事要看到,在自动驾驶汽车撞到墙上之前,一个可爱的[沙漏]@987654327 @ 当它在控制系统忙碌的时候移动沙子,不管背后是什么原因,以一种破坏性的阻塞方式。

量化目标对测试有意义。

如果给定的阈值允许有 500 毫秒的稳定范围(这对于慢动作液压执行器/控制回路来说可能是一个安全值,但可能无法用于导弹控制系统,那么对于任何[mass&momentum-of-inertia]-less 系统(类似于 RT 控制系统的 DSP 系列),如果您的处理介于两者之间,您可以进行端到端测试。

如果您知道,您的传入数据流每 500 us 带来大约 10 kB,您可以测试您的设计是否能够跟上突发流量的步伐。

如果您进行测试,您的模型设计确实没有达到您非常清楚的目标(不满足性能/时间受限的数据),即设计或架构需要改进的地方。

【讨论】:

    【解决方案2】:

    首先确保您在不同的物理内核(不是 HT)上运行生产者和消费者。 其次,它在很大程度上取决于硬件和操作系统。上次我测量内核 IO(4-5 年前)时,结果确实是 10 到 20us 左右的 send/recv 系统调用。 您必须将内核设置优化为低延迟并设置 TCP_NODELAY。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-14
      • 2013-03-13
      • 1970-01-01
      相关资源
      最近更新 更多