简体   繁体   English

C:Linux套接字:Recvfrom()在获取UDP数据包时太慢

[英]C : Linux Sockets: Recvfrom() too slow in fetching the UDP Packets

I am receiving UDP packets at the rate of 10Mbps . 我正在以10Mbps的速率接收UDP数据包。 Each packet is formed of around 1109 bytes . 每个数据包由大约1109字节组成 So, it makes more than 1pkt/ms that I am receving on eth0 . 因此,它在eth0上接收的数据超过1pkt / ms The recvfrom() in C receives the packet and passes on the packet to Java. C语言中的recvfrom()接收数据包并将该数据包传递给Java。 Java does the filtering of the packets and the necessary processing. Java对数据包进行过滤并进行必要的处理。

The bottlenecks are: 瓶颈是:

  1. recvfrom() is too slow:fetching takes more than 10ms possibly because it does not get the CPU. recvfrom()太慢:获取时间超过10毫秒,可能是因为它没有获取CPU。

  2. Passing of the packet from C to Java through the interface(JNI) takes 1-2 ms. 数据包通过接口(JNI)从C传递到Java需要1-2毫秒。

  3. The processing of packet in Java itself takes 0.5 to 1 second depending on if database insertion or image processing needs to be done. Java本身对数据包的处理需要0.5到1秒,具体取决于是否需要进行数据库插入或图像处理。

So, the problem is many delays add up and more than half of the packets are lost. 因此,问题在于许多延迟加起来,并且一半以上的数据包丢失。

The possible solutions could be: 可能的解决方案可能是:

  1. Exclude the need for C's recvfrom() completely and implement UDP fetching directly in Java (Note: On the first place, C's recvfrom() was implemented to receive raw packets and not UDP). 完全不需要C的recvfrom()并直接在Java中实现UDP提取(注意:首先,实现C的recvfrom()的目的是接收原始数据包,而不是UDP)。 This solution may reduce the JNI transfer delay. 该解决方案可以减少JNI传输延迟。

  2. Implement multi-threading on the UDP receive function in Java. 在Java中的UDP接收功能上实现多线程。 But then an ID shall be required in the UDP packets for the sequence because in multi-threading the order of incoming packets is not guaranteed. 但是,随后在UDP数据包中必须为该序列指定一个ID,因为在多线程处理中,无法保证传入数据包的顺序。 (However, in this particular program, there is a need for packets to be ordered). (但是,在此特定程序中,需要对数据包进行排序)。 This solution might be helpful in receiving all packets but the protocol which sends the data needs to be modified to add a sequence identifier. 此解决方案在接收所有数据包方面可能会有所帮助,但是发送数据的协议需要修改以添加序列标识符。 Due to multi-threading, the receiver might have higher chances to get the CPU and packets can be quickly fetched. 由于具有多线程,接收方可能有更高的机会获得CPU,并且可以快速获取数据包。

  3. In Java, a blocking queue can be implemented as a huge buffer which stores the incoming packets. 在Java中,可以将阻塞队列实现为存储传入数据包的巨大缓冲区。 The Java parser can then use the packets from this queue to process it. 然后,Java解析器可以使用来自此队列的数据包来对其进行处理。 However, it is not sure if the receiver function will be fast enough and put all the received packets in the queue without dropping any packet. 但是,不确定接收器功能是否足够快并且是否将所有接收到的数据包放入队列中而不丢弃任何数据包。

I would like to know which of the solutions could be optimal or a combination of the above solutions will work. 我想知道哪种解决方案可能是最佳的,或者将上述解决方案结合使用即可。 Any help or suggestions would be greatly appreciated. 任何帮助或建议,将不胜感激。

How long is this burst going on? 这种爆发持续多长时间? Is it continuous and will go on forever? 它是连续的,并且会永远持续下去吗? Then you need beefier hardware that can handle the load. 然后,您需要功能更强大的硬件来处理负载。 Possibly some load-balancing where multiple servers handle the incoming data. 可能是一些负载平衡,其中多个服务器处理传入的数据。

Does the burst only last a short wile, like in at most a second or two? 爆发只会持续一小会儿,最多一两秒吗? Then have the lower levels read all packets as fast as it can, and put in a queue, and let the upper levels get the messages from the queue in its own time. 然后,让较低的级别尽可能快地读取所有数据包,并将其放入队列中,然后让较高的级别在自己的时间内从队列中获取消息。

It sounds like you may be calling recvfrom() with your socket in blocking mode, in which case it will not return until the next packet arrives. 听起来您可能在套接字处于阻塞模式的情况下正在调用recvfrom() ,在这种情况下,直到下一个数据包到达时,它才会返回。 If the packets are being sent at 10ms intervals, perhaps due to some delay on the sending side, then a loop of blocking recvfrom() calls would appear to take 10ms each. 如果数据包以10ms的间隔发送,可能是由于发送方的某些延迟,则阻塞recvfrom()调用的循环似乎每个都要花费10ms。 Set the socket to non-blocking and use something like select() to decide when to call it. 将套接字设置为非阻塞状态,并使用类似select()来决定何时调用它。 Then profile everything to see where the real bottleneck lies. 然后分析所有内容以查看真正的瓶颈所在。 My bet would be on one or more of the JNI passthroughs. 我的赌注将在一个或多个JNI传递上。

Note that recvfrom() is not a "C" function, it is a system call. 请注意, recvfrom()不是“ C”函数,它是系统调用。 Java's functions just add layers on top of it. Java的功能只是在其之上添加层。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM