- 论坛徽章:
- 0
|
epoll 多线程使用问题
关于epoll 的基本用法,我相信大家很熟悉
简单描述一下
在epoll过程中, 我们基本是epoll_wait 等待到我们
想要的事件, 并且从epoll 返回的event 里面 找出事件,找到相应
的socket 和 unit, 进行操作
我简单描述一下 我的做法
map
socket, void *
socket 代表 目前的socket
void * 代表 和它相关的unit 对象
当unit 希望等待socket 获取数据, 那么 我们首先将socket ,和读条件
加入epoll 的fd. 当返回的时候, 我们可以从map 里,获取socket => unit 对象
更好一点的做法, 我们可以将socket, unit 2者捆绑成一个结构, 将指针放入 epoll 的fd.
在epoll 返回时候,我们就能直接使用,免除了 再次查找了。 但是这只是一个小的性能改进
我目前的epoll 的处理方式 是
while ( epoll_wait()) {
// 遍历整个返回结果集 处理
...
...
...
//1-3 将新socket 加入epoll_fd
}
很明显,这是一个低效的单线程处理过程。 即使你的cpu 核再多 也是无法多核的好处。
所以 我想采用一个更高效的处理办法。
第一步
while ( epoll_wait()) {
// 将相关的socket 从epoll 里面删除,不再关心它发生的事件
// 如果不去除, 就会出现重入问题, 就是这个socket 新事件到达,
// 而前一个线程可能还没有处理好。当然我们也可以用精确控制2个线程
// 操作1 个对象,但这太容易出问题了。
// 将结果集copy 出去
...
...
...
//1-3 将新socket 加入epoll_fd
}
第二步
多线程,以工作者的方式,不断的领取结果集,处理。
处理完以后,根据情况,决定是否要再次加入epoll_fd.
现在的问题是, 这样意味着,一次操作 就要进行一次出入epoll_fd 操作。
比如 一个http 访问,正常情况,会返回5-8 次read 事件, 那么我就需要
5-8 次的进入epoll_fd . 这样的效率是否会很低。
epoll_fd 是在任何时候都可以加入的吗? 我目前做法比较固定,需要
在epoll_wait 返回后,才进行, 也就是在1-3 的地方进行。 如果为提高性能。
多线程必然在epoll_wait 没有返回的情况下,加入,所以这样是否安全,
我并不知道(我尝试过,有些问题,但不敢保证是epoll本身造成的)。
而且这样也会带来一些 事务不完整的问题。
无论如何 这都是一个新的性能瓶颈
不知道大家的epoll 架构是怎么做的? 我发现在这点上windows 的完成端口到是
简单了很多, 它简单的一次返回,不会有这个问题。
|
|
|