在接收缓冲区中累积数据,以防止在 epoll_waiting 慢速连接时出现忙等待
Accumulate data in receive buffer in order to prevent busy-waiting when epoll_waiting on slow connections
使用足够慢的互联网连接发送足够大量数据的客户端导致我在 C 中带有套接字的经典非阻塞服务器-客户端设置中忙于等待。
忙等是这个过程造成的
- 我安装
EPOLLIN
客户端,(监听接收数据)
- 客户端发送数据。
epoll_wait
表示有数据要读取 (EPOLLIN
)
- 正在恢复协程,正在使用数据,需要更多数据才能完成此客户端。
EWOULDBLOCK
回到 1.
上述过程正在重复几分钟(由于互联网连接速度慢和数据量大)。除了消耗 cpu 时间之外,它基本上只是无用的跳来跳去,没有做任何有意义的事情。此外,它有点扼杀了 epoll_wait
.
的目的
所以,我想通过某种机制避免这种忙等待,这种机制确实会在接收缓冲区中累积数据,直到达到最小大小或自第一个字节到达以来已经过了最大超时,然后才 epoll_wait
应该为这个客户用 EPOLLIN
叫醒我。
我首先查看了 tcp(7),我希望有类似 TCP_CORK
的东西,但对于接收缓冲区,却找不到任何东西。
然后我查看了 unix(7) 并尝试在第 3 步之后通过 SIOCINQ
自己实现它。问题是我最终再次忙于等待,因为第 3 步将立即进行return 因为数据可供读取。或者我可以在 3. 之后立即注销客户端,但这会阻止这个特定的客户端,直到 epoll_wait
returns 来自不同的客户端。
是否陷入僵局,或者是否有解决上述问题的方法,可以在接收缓冲区中以最小大小或最大时间累积数据而无需忙等待?
@ezgoing 和我详细讨论了这个问题,我相信这不是问题(@user207421 也指出)。
当我第一次读到这个问题时,我想也许他们担心的是微小的数量(比如,一次 16 个字节),这本来值得研究,但一旦发现它一次是 4KiB , 这太常规了,不值得研究。
有趣的是,串行 I/O 模块确实支持这一点,其模式只有在这么多字符可用或经过这么多时间后才会唤醒,但网络模块没有这样的功能。
唯一值得解决的问题是,如果有实际证据表明它正在以有意义的方式影响应用程序的响应能力,而不是对数据包速率的假设性关注。
使用足够慢的互联网连接发送足够大量数据的客户端导致我在 C 中带有套接字的经典非阻塞服务器-客户端设置中忙于等待。
忙等是这个过程造成的
- 我安装
EPOLLIN
客户端,(监听接收数据) - 客户端发送数据。
epoll_wait
表示有数据要读取 (EPOLLIN
)- 正在恢复协程,正在使用数据,需要更多数据才能完成此客户端。
EWOULDBLOCK
回到 1.
上述过程正在重复几分钟(由于互联网连接速度慢和数据量大)。除了消耗 cpu 时间之外,它基本上只是无用的跳来跳去,没有做任何有意义的事情。此外,它有点扼杀了 epoll_wait
.
所以,我想通过某种机制避免这种忙等待,这种机制确实会在接收缓冲区中累积数据,直到达到最小大小或自第一个字节到达以来已经过了最大超时,然后才 epoll_wait
应该为这个客户用 EPOLLIN
叫醒我。
我首先查看了 tcp(7),我希望有类似 TCP_CORK
的东西,但对于接收缓冲区,却找不到任何东西。
然后我查看了 unix(7) 并尝试在第 3 步之后通过 SIOCINQ
自己实现它。问题是我最终再次忙于等待,因为第 3 步将立即进行return 因为数据可供读取。或者我可以在 3. 之后立即注销客户端,但这会阻止这个特定的客户端,直到 epoll_wait
returns 来自不同的客户端。
是否陷入僵局,或者是否有解决上述问题的方法,可以在接收缓冲区中以最小大小或最大时间累积数据而无需忙等待?
@ezgoing 和我详细讨论了这个问题,我相信这不是问题(@user207421 也指出)。
当我第一次读到这个问题时,我想也许他们担心的是微小的数量(比如,一次 16 个字节),这本来值得研究,但一旦发现它一次是 4KiB , 这太常规了,不值得研究。
有趣的是,串行 I/O 模块确实支持这一点,其模式只有在这么多字符可用或经过这么多时间后才会唤醒,但网络模块没有这样的功能。
唯一值得解决的问题是,如果有实际证据表明它正在以有意义的方式影响应用程序的响应能力,而不是对数据包速率的假设性关注。