资讯专栏INFORMATION COLUMN

epoll LT/ET 深入剖析

microelec / 2113人阅读

摘要:深入剖析事件有两种模型水平触发接收缓冲区不为空有数据可读读事件一直触发发送缓冲区不满可以继续写入数据写事件一直触发符合思维习惯,返回的事件就是的状态边沿触发的接收缓冲区状态变化时触发读事件,即空的接收缓冲区刚接收到数据时触发读事件的发送缓冲

epoll LT/ET 深入剖析

EPOLL事件有两种模型:

Level Triggered (LT) 水平触发
.socket接收缓冲区不为空 有数据可读 读事件一直触发
.socket发送缓冲区不满 可以继续写入数据 写事件一直触发
符合思维习惯,epoll_wait返回的事件就是socket的状态

Edge Triggered (ET) 边沿触发
.socket的接收缓冲区状态变化时触发读事件,即空的接收缓冲区刚接收到数据时触发读事件
.socket的发送缓冲区状态变化时触发写事件,即满的缓冲区刚空出空间时触发读事件
仅在状态变化时触发事件

ET还是LT?

LT的处理过程:
. accept一个连接,添加到epoll中监听EPOLLIN事件
. 当EPOLLIN事件到达时,read fd中的数据并处理
. 当需要写出数据时,把数据write到fd中;如果数据较大,无法一次性写出,那么在epoll中监听EPOLLOUT事件
. 当EPOLLOUT事件到达时,继续把数据write到fd中;如果数据写出完毕,那么在epoll中关闭EPOLLOUT事件

ET的处理过程:
. accept一个一个连接,添加到epoll中监听EPOLLIN|EPOLLOUT事件
. 当EPOLLIN事件到达时,read fd中的数据并处理,read需要一直读,直到返回EAGAIN为止
. 当需要写出数据时,把数据write到fd中,直到数据全部写完,或者write返回EAGAIN
. 当EPOLLOUT事件到达时,继续把数据write到fd中,直到数据全部写完,或者write返回EAGAIN

从ET的处理过程中可以看到,ET的要求是需要一直读写,直到返回EAGAIN,否则就会遗漏事件。而LT的处理过程中,直到返回EAGAIN不是硬性要求,但通常的处理过程都会读写直到返回EAGAIN,但LT比ET多了一个开关EPOLLOUT事件的步骤

LT的编程与poll/select接近,符合一直以来的习惯,不易出错
ET的编程可以做到更加简洁,某些场景下更加高效,但另一方面容易遗漏事件,容易产生bug

这里有两个简单的例子演示了LT与ET的用法(其中epoll-et的代码比epoll要少10行):
https://github.com/yedf/handy/blob/master/raw-examples/epoll.cc
https://github.com/yedf/handy/blob/master/raw-examples/epoll-et.cc

针对容易触发LT开关EPOLLOUT事件的情景(让服务器返回1M大小的数据),我用ab做了性能测试
测试的结果显示ET的性能稍好,详情如下:
LT 启动命令 ./epoll a
ET 启动命令 ./epoll-et a
ab 命令:ab -n 1000 -k 127.0.0.1/
LT 结果:Requests per second: 42.56 [#/sec] (mean)
ET 结果:Requests per second: 48.55 [#/sec] (mean)

当我把服务器返回的数据大小改为48576时,开关EPOLLOUT更加频繁,性能的差异更大
ab 命令:ab -n 5000 -k 127.0.0.1/
LT 结果:Requests per second: 745.30 [#/sec] (mean)
ET 结果:Requests per second: 927.56 [#/sec] (mean)

对于nginx这种高性能服务器,ET模式是很好的,而其他的通用网络库,更多是使用LT,避免使用的过程中出现bug

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/39240.html

相关文章

  • android源码分析-深入MessageQueue

    摘要:相当于层的初始化。注意,这里是层层自己的消息,与层的没关系。好吧,这个过程基本上分析完毕了,其实就是通过不断的处理消息,并且调用消息的回调。 承接上文在looper中会在一开始就创建一个MessageQueue,并且在loop中每次都会从其中取出一个message处理。那么我们就来看看这个MessageQueue: MessageQueue(boolean quitAllowe...

    LeexMuller 评论0 收藏0
  • nginx 事件模块简单剖析

    摘要:我们这里以单进程启动为例中的函数调用这个函数回循环调用中的事件循环的核心函数是。这个方法仅在方法中调用,它是处理,分发事件的核心初始化事件驱动模块的方法退出事件驱动模块前调用的方法。读事件的回调函数是这样就进入了框架处理流程 我们这里以单进程启动为例nginx.c中的main 函数调用ngx_single_process_cycle 这个函数回循环调用 ngx_process_cy...

    huayeluoliuhen 评论0 收藏0

发表评论

0条评论

microelec

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<