在进行网络编程的时候,我们经常会听到阻塞IO,非阻塞IO等概念。并且大家都在说阻塞IO的性能差。那么什么才是阻塞IO?阻塞IO的性能为什么那么差?IO多路复用为什么就能够提升性能呢?下面我根据自己对这方面的学习来一一分析。
什么是阻塞IO?阻塞IO主要是指进程为了等待某个事件的发生而主动让出CPU,从运行态转为就绪态,等到对应的事件发生了才从就绪态转变为运行态。
为什么会说阻塞IO的开销大呢?网络上很多文章,包括一些书籍都说阻塞IO的性能差,但事实上并不能说阻塞IO的性能差,只能说阻塞IO的开销较大。
为什么阻塞IO的开销较大呢?
前面我们讲过,阻塞会使线程有运行态转变为就绪态,那么就对应一次进程的上下文,进程上下文切换会切换虚拟内存,栈,全局变量等资源,需要花费比较多的时间,而且等待的事件发生之后,就还会从就绪态转变为运行态,这里有涉及到进程的上下文切换,那么这样一次同步的阻塞IO就会导致两次的进程上下文切换。所以说阻塞IO的开销比较大。
为什么不可以说阻塞IO的性能差呢?
只有一个阻塞IO的性能不差,大量的阻塞IO,从而导致大量的进程上下文切换性能才会差。
IO多路复用为什么能够提升性能?IO多路复用一般指select,poll以及epoll(以上均是linux上的)。其中性能最好的就是epoll。epoll高性能的主要原因是无须进行大量的进程上下文切换。(与epoll中的红黑树无关)
epoll的主要工作流程是在使用epoll_creat()创建好event_poll内核对象之后,在通过epoll_ctl()将socket加入到epoll中,最后通过epoll_wait()开监听就绪队列是否有事件的发生。其中epoll连接到的socket都是无须挂起的,这里不会设计进程的上下文切换(epoll的详细内容内容请看我的另一篇博客)。
epoll会存在阻塞吗?
会的,在使用epoll_wait()访问就绪队列的时候,如果没有就绪事件,epoll对应的进程就会主动让出CPU。
但是在高并发中,一般epoll_wait()都可以获得就绪事件,所以一般不会主动让出CPU。



