2. poll(线程不安全):它和select在本质上没有多大差别,但是poll没有最大文件描述符数量的限制
3. epoll(线程安全):epoll可以同时支持水平触发和边缘触发(Edge Triggered,只告诉进程哪些文件描述符刚刚变为就绪状态,它只说一遍,如果我们没有采取行动,那么它将不会再次告知,这种方式称为边缘触发),理论上边缘触发的性能要更高一些,但是代码实现相当复杂。
python异步实现
多进程 + 协程 + callback(io多路复用做事件驱动)
协程 第三方封装库:
?
gevent = greenlet + python.monkey(底层使用 libevent 时间复杂度: O(N * logN))
? ?
meinheld = greenlet + picoev (时间复杂度: O(N) )
? ?
eventlet
?
picoev和libevent
黑马程序员免费视频库:http://yun.itheima.com?2020sxkyk
meinheld和gevent都能实现异步,但是测评中meinheld比gevent的性能好很多,不过因为meinheld支持的比较少,一般都是配合gunicorn使用的。下面分析一下meinheld和gevent性能差距主要原因,分别使用的是picoev和lievent。
# libevent
主要实现:使用堆(优先队列)作为timer事件的算法(nlogn),IO和信号的实现均使用了双向队列(用链表实现)。
时间复杂度: O(N * logN)
# picoev
picoev:根据作者简介,主要优化有两点。
1. 主要是考虑是fd(file descriptors)在unix中是用比较小的正整数表示的,那么把fd的相关信息,全部存储在一个array中,这样使得查找快速,在操作socket状态时会更加的快。
黑马程序员免费视频库:http://yun.itheima.com?2020sxkyk
2. 第二点是对于timer事件的算法优化,通过环形缓冲区(128)和bit vector实现查看部分源码可以看出,主要实现是每个时间点对应的是缓冲区的一个位置,
每个缓存区使用bit vector 表示fd的数值,相当于一种hash映射所以时间复杂度为(o(n)),n为那个缓存区所存的fd数量。
时间复杂度: O(N)
性能: picoev > libevent
理解----协程&线程&进程
黑马程序员免费视频库:http://yun.itheima.com?2020sxkyk