Vik*_*ram 11 c sockets linux performance networking
我正在编写一个代码,它从服务器每隔1ms接收一次原始以太网数据包(无TCP/UDP).对于收到的每个数据包,我的应用程序必须回复14个原始数据包.如果服务器在每1ms发送一次数据包之前没有收到14个数据包,则服务器会发出警报并且应用程序必须中断.服务器 - 客户端通信是一对一链接.
服务器是硬件(FPGA),以精确的1ms间隔生成数据包.客户端应用程序在具有10G SolarFlare NIC的Linux(RHEL/Centos 7)计算机上运行.
我的第一个代码版本是这样的
while(1)
{
while(1)
{
numbytes = recvfrom(sockfd, buf, sizeof(buf), 0, NULL, NULL);
if(numbytes > 0)
{
//Some more lines here, to read packet number
break;
}
}
for (i=0;i<14;i++)
{
if (sendto(sockfd,(void *)(sym) , sizeof(sym), 0, NULL, NULL) < 0)
perror("Send failed\n");
}
}
Run Code Online (Sandbox Code Playgroud)
我通过clock_gettime在recvfrom呼叫之前采用时间戳(使用)和在呼叫之后采用时间戳来测量接收时间,我打印这些时间戳的时间差并在时间差超过900-1100 us的允许范围时打印它们.
我面临的问题是数据包接收时间是波动的.这样的事情(打印是以微秒为单位)
Decode Time : 1234
Decode Time : 762
Decode Time : 1593
Decode Time : 406
Decode Time : 1703
Decode Time : 257
Decode Time : 1493
Decode Time : 514
and so on..
Run Code Online (Sandbox Code Playgroud)
有时解码时间超过2000us,应用程序会中断.
在这种情况下,应用程序将在2秒到几分钟之间的任何地方中断.
我试过的选项到现在为止.
SCHED_FIFOrecvfrom使用poll(),select()电话旋转.所有这些选项都比初始版本的代码有了显着的改进.现在应用程序将运行约1-2个小时.但这仍然不够.
一些观察:
请提示是否有其他方法可以改善应用程序的运行时间.
提前致谢.
首先,需要验证时间戳方法的准确性;时钟获取时间。分辨率为纳秒,但准确度和精确度值得商榷。这不是您问题的答案,但会在继续之前告知时间戳的可靠性。看到CLOCK_REALTIME 和 CLOCK_MONOTONIC 之间的区别吗?为什么您的应用程序应使用 CLOCK_MONOTONIC 。
我怀疑大部分解码时间波动是由于每次解码的操作次数不同、操作系统的上下文切换或 IRQ 造成的。
每个解码的操作我无法评论,因为代码已在您的帖子中简化。还可以分析和检查此问题。
可以轻松检查和监控每个进程的上下文切换https://unix.stackexchange.com/a/84345
正如罗恩所说,这些对于网络来说是非常严格的时序要求。它必须是一个孤立的网络,且用途单一。您对 ssh'ing 时解码超时的观察表明必须阻止所有其他流量。鉴于单独的网卡,这令人不安。因此我怀疑 IRQ 是问题所在。请参阅/proc/中断。
为了在较长的时间间隔(数小时到数天)内实现一致的解码时间,需要大幅简化操作系统。删除不必要的进程和服务、硬件,也许还可以构建自己的内核。一切都是为了减少上下文切换和中断的目标。此时应考虑实时操作系统。这只会提高解码时间一致的概率,但不能保证。
我的工作是开发一个结合了 FPGA ADC、PC 和以太网的数据采集系统。不可避免的是,多功能 PC 的不一致性意味着某些功能必须转移到专用硬件上。考虑为 PC 开发应用程序与将其迁移到硬件的优缺点。