1

我有一个 UDP 网络应用程序,它读取发送给它的数据包,然后处理它们(相同的线程)。读取是非阻塞的,所以我没有使用轮询或选择。

收到的数据包按会话分组。

工作取决于是否有正在进行的会话。如果没有工作要做,即没有会话,或者没有要处理的数据包,那么我需要旋转。

我一直在看这里找到的混合算法: http ://www.1024cores.net/home/lock-free-algorithms/tricks/spinning

一直在玩它。有人告诉我,这更多是为了忙碌的等待。您使用什么方法来防止不必要的处理和不必要的高 CPU 使用率?

编辑:

感谢所有的答案和评论。我现在正在做以下事情。当谈到从网络阅读时,我会看看是否还有其他工作要做。如果有,那么我调用 poll 超时为零。然后我尽可能多地读取数据包并将它们放入内存队列中进行处理。如果没有其他工作,那么我会无限期地投票(即-1)。它似乎运作良好,CPU只有在事情繁忙时才高,否则它会下降到零。

4

3 回答 3

3

如果您无事可做,则应该阻塞-如果不是在套接字本身上(即,如果它是一个处理多个网络套接字或事件类型的事件循环),那么在发生某些事情时发出信号的门上(设计取决于您的操作系统如何执行异步 I/O)。

旋转是您仅在等待短的时间(通常仅在内核模式下)时才应该做的事情。

于 2011-04-13T06:07:50.820 回答
1

您每秒处理多少个数据包?处理这些数据包需要多长时间?如果你使用阻塞线程,你得到的平均 CPU 使用率是多少?

除非阻塞等待接近 100% 的使用率,从阻塞本身中减少一些性能会有所帮助,否则旋转不会提高性能,反而会降低性能。通过旋转,您锁定了一个无法运行其他代码的内核(可能包括为您提供工作的代码:即读取网络并将数据包传递给您的应用程序的内核代码),您在不执行任何工作的情况下消耗资源根本...

请注意,当文章说编写阻塞代码比编写非阻塞自旋等待更难时,作者并不是在谈论在系统中实现了阻塞版本的操作,而是针对线程必须等待某个条件的情况由其他线程触发(共享变量值高于/低于限制,更改标志......)。

此外,如果检查条件的成本很高,那么循环的每次迭代都会产生自旋的成本,这可能会超过检查一次并执行昂贵的等待的成本。

请记住,旋转是一种主动等待询问如何在不消耗处理器的情况下主动等待是没有意义的,因为主动等待方法意味着消耗处理器时间。您可以做些什么来避免不必要的 CPU 使用?使用阻塞调用来获取下一个数据包。在读取 UDP 数据包的特定情况下,我怀疑两次调用非阻塞读取在处理时间上不会比一次调用阻塞读取操作更昂贵。

再次思考一开始的问题,可以概括为:阻塞是否被证明是瓶颈?*在这种情况下,主动等待是否真的有帮助?*

于 2011-04-13T07:37:52.430 回答
1

由于您必须从套接字读取,因此您可以进行阻塞读取。没有数据包,你就没有理由跑步,对吧?

如果有多个套接字,则阻塞读取将不起作用,因此您需要pselect()来监视多个描述符。

我错过了一些明显的东西吗?

我突然想到,在你收到数据报之后,你可能会有一些长期的处理。如果您使用非阻塞 I/O 的原因是为了避免在处理会话时忽略传入流量,那么在这种情况下,显而易见的做法是 fork() 会话。(嗯,所以我仍然认为我一定错过了什么......)

于 2011-04-13T05:53:36.313 回答