我发现啊,skynet里面的pipe用法有问题,因为是阻塞的,一次只能处理(发送一个数据包),如果同时有1000个链接由一个epoll管理,又假如每个链接进来1个 『More』
我没看明白.
skynet 对 IO 是单线程串行分发的, 如果出现拥塞跟 pipe 无关. pipe 就是用来把 IO 处理串行化.
而 skynet 的设计目的是处理 CPU 高负载的业务, 而不是 IO 高负载的业务. - 回复 | (2711) | 云风 | 2013-12-16 03:13:02
语文不好.首先我的理解是,你用pipe的目的就像zeromq一样,用来做线程间通信,减少锁,这个我也觉得很好.而我所说的跟IO高负载没关,指的是并发能力,即每秒 『More』 - 回复 | (2713) | 囧 | 2013-12-16 11:37:24
我明白你的意思. 但实际上 cpu 和 IO 都没有浪费, 只是延迟变长了而已. 因为 epoll 循环是满负荷运转的.你最初的例子中说 "发送端会积累大量的包来不及发送" 那么之所以累积也是因为输入流还在源源不断的来.
这样解释: 你是希望通过非阻塞 pipe 作到内部产生的消息(发送) 可以尽可能的在一个 epoll 消息中处理. 也就是收到 100 个请求, 可以立刻处理这 100 个请求所产生的回应. 而不是把 recvctrl_fd 的处理分摊到这些请求中.
但实际上, 这么做并没有劣化处理能力. 比如你把 1 万个请求包全部一次发送完, 而不是等每个包的请求回应后再发下一个的话, 处理全部包的总时间并没有变长.
这就是我说的, skynet 需要处理的是 CPU 高负载的业务, 而不是 IO 高负载的. CPU 高负载的情况下, 并不能对接收的包立刻回应. 发送回应被推迟并没有空挂 CPU , 只是被排到队列里去了.
这种业务下, IO 上的业务数量增加后, 系统的处理能力限制并不在 IO 的反应速度上,而是在 CPU 的处理能力上. 在 IO 线程满载时, 当输入过多, 优先接收到新的请求(尽可能的收),推迟已经处理完的请求 使回应延迟可能是件好事.
如果不希望这样, 可以在 pipe 的阻塞接收后,再 select 一下, 如果还有数据就继续处理就可以了. 但这样其实并不增加系统的吞吐量.
谢谢大大解释。我并没有"把 1 万个请求包全部一次发送完",recvctrl_fd读到发送包并不是马上发送出去,而是把包挂到各个client_fd的发送队列上,然后设置client_fd的EPOLLOUT事件,统一由epoll来管理调度。对于游戏来说,我觉得反应速度也很重要啊,我搞页游的。 - 回复 | (2717) | 3q | 2013-12-18 02:34:55