Libfly协程库实现与原理——协程的优点与用处
为什么写一个协程库?协程有什么优点?这些问题非常重要,在做一件事情前需要一个做他的最初动力对吧。
我们先说一个普通的server模式 reactor:
这里有一个半同步/半异步模式的多线程结构,主线程监听socket,把相应的事件放入请求队列,然后工作线程进行在队列中取出事件,并执行相应的I/O。
现在问题来了,这样的模式有没有CPU浪费那?
显然是有的
1. epoll_wait(100ms),epoll等待事件该线程会阻塞,占用一个CPU核
2. 线程间切换以及锁的争用的浪费CPU
想一下如果是一个8核的CPU,1个核用于epoll_wait(),7个核是用于工作线程,在当一个事件来临时,要通过条件变量,互斥锁,唤醒工作线程。这个过程是通过内核线程调度来实现的,但一定不会是最优的。因为你不知道内核是怎么调度的,优先级是什么,你也无法直接操作唤醒某个线程。
那么现在我不想通过内核来调度了,我觉得它太浪费时间,不如我自己来调度,那么协程就起作用了,我用一个线程执行epoll_wait(),也同样是在这个线程,我创建多个工作协程,epoll_wait(),有事件发生后,我就直接在线程内调用工作协程。这样我就实现了异步调用,且不用切换线程,只需要在一个协程完成这些工作,这样是不是就节省了CPU的调用了。
对于同步I/O的模式,协程是异步I/O可以节省CPUI/O等待时间。
对于异步I/O的模式,协程可以节省进程间的切换和锁的争用时间。
好那么我现在分析一下使用协程的server架构图:
协程本身就是单线程的,其采用异步+回调的方式。但是其逻辑流非常清晰。用同步编程的思想就可以轻松完成异步模式。
既然协程本身是单线程的,他可以把单核的CPU高效利用,但多核的怎么办那?
那就用多线程来解决了。多线程加多协程,是不是就可以高效的利用CPU了。
现在来总结一下协程的优点:
一、相对于异步I/O模式
1. 编程思想简单,逻辑流清楚,按照同步编程的思想编程就OK。
2. 相对于线程切换上下文开销小,其只保存一些寄存器的值。
3. 不需要锁的争用,线性的逻辑流。
4. 高并发,一个CPU可以支持千万协程。
5. 在用户态完成异步调度,不需要进入内核态,也不需要内核进行调度
一、相对于同步I/O模式
1. 节省线程I/0阻塞时间,实现异步模式。
2. 相对于线程切换上下文开销小,其只保存一些寄存器的值。
3. 高并发,一个CPU可以支持千万协程。
4. 在用户态完成异步调度,不需要进入内核态,也不需要内核进行调度
我觉得这个问题是随着个人经验不断丰富之后才会慢慢总结下来,我以后会继续完善,并把我的一些思考分享出来。