水平触发或边缘触发更高效吗?

Ale*_*lex 12 c linux epoll

我试图弄清楚什么是更高性能,边缘触发或水平触发的epoll.

主要是我正在考虑"高性能":

  1. 能够处理多个连接而无需降级.

  2. 能够保持每个入站消息的最高速度.

我实际上更关心#2,但#1也很重要.

我一直在使用单线程使用者(使用接受/读取多个套接字连接epoll_wait)和多个生产者运行测试.

到目前为止,我看到没有区别,甚至多达1000个文件描述符.

我一直在努力工作(妄想?)边缘触发应该更高效,因为将会收到更少的中断.这是正确的假设吗?

我的测试的一个问题,可能是掩盖性能差异,是我收到后不会将我的消息发送给线程,因此中断次数越少并不重要.我一直不愿意做这个测试,因为我一直在使用__asm__ rdtsc我的"时间戳",所以我不想调和我的原始时间戳来自哪个核心.

让我更加怀疑的是,在我看到的一些基准测试中,水平触发的epoll表现更好.

哪个更好?在什么情况下?没有区别吗?任何见解将不胜感激.

编辑:

我的套接字是非阻塞的.

cme*_*erw 9

我不希望在边缘和水平触发之间看到巨大的性能差异.

对于边沿触发,你总是要排空输入缓冲区,所以你有一个无用的(只返回EWOULDBLOCK)recv系统调用.但是对于级别触发,您可能会使用更多epoll_wait系统调用.正如手册页指出的那样,在水平触发模式下避免饥饿可能会稍微容易一些.

真正的区别在于,当您想要使用多个线程时,您必须使用边缘触发模式(尽管您仍然必须小心获得正确的同步).

  • 对于多线程,oneshot 语义 (EPOLLONESHOT) 也可能有用。 (2认同)
  • 是的,因为对于某些人来说水平仍然是"可读的"(在实际读取数据之前的短时间内),所有线程都将被唤醒.另一方面,对于边缘触发,您只能获得单个线程被唤醒的单个状态转换. (2认同)
  • 实际上不需要“无用的” EWOULDBLOCK recv 系统调用。如果 recv 返回小于 max-read-size ,那么您可以确定此时内核缓冲区是空的,即使它在您处理数据期间填满 epoll_wait 也会再次通知您(在 EPOLLET 模式下)。因此,在不太可能的情况下,recv-buffer 的大小正好是消息的长度,才需要无用的调用。 (2认同)
  • 关于最后一点,读<max只是一个提示,绝不是保证.过去我们遇到过一些问题,其中一些内核端优化导致在套接字上的单个recv()中返回的请求少于请求,其中使用GRO接收的数据仍然未决. (2认同)