1
chenluois 2011-12-06 16:12:09 +08:00
汗~ 看到标题,我还以为是说双馨老师呢!
|
2
funcman OP 老师那是AOI
|
3
ssword 2011-12-06 16:31:18 +08:00
|
6
ssword 2011-12-06 16:55:56 +08:00
@funcman 并发和负载都是很实际的问题。从问题到解决方案,都是从实际出发的。你问为什么要有异步IO,那可以实实在在的回答:解决或者缓解高并发的瓶颈问题,也就是C10K问题。
但是楼主对异步IO是怎样看的?如果对并发模型有部分常识,是不会将问题做二分法处理的。"异步IO"其实是个很含糊的称呼。起码非阻塞IO != 异步IO。 楼主说同样消耗资源,不错,但是消耗资源的多少有区别,这点细微的区别就可以成为瓶颈。比如,多线程+阻塞IO就比单线程+select/poll更浪费一分资源,select/poll又不如kqueue/epoll/iocp省资源。 好,既然epoll/kqueue是最终形态,大家还要其它模型做什么?非阻塞IO很难编程,很难调试。这就是得到性能的代价。至于actor模式等等,则是为了中和这部分复杂度而生的。 |
8
haohaolee 2011-12-06 17:04:54 +08:00
只对IOCP有些认识,如果由OS来做IO,各种IO优化可以由OS来做,而且系统调用的次数会少些,而系统调用是很消耗指令周期的,但是缺乏灵活性。这里我是拿reactor和proactor比的。貌似通常情况下两者都被称为异步IO吧
|
9
moole 2011-12-06 18:33:26 +08:00
Reactor模式需要处理IO,Proactor把IO交给底层,所以后者比前者应该更利用上层通用性的封装。
|
10
funcman OP @ssword
如果只是说阻塞/非阻塞、同步/异步,恐怕还是不能讲得太清。 阻塞发生在什么地方,一般来说发生在应用层向传输层的数据交换上。我们send/recv,实际上是与传输层打交道。比如recv,我们是把传输层的读缓冲区的数据搬到用户缓存区中,如果读缓冲区不可读(比如没数据),那阻塞模式下用户程序会停在的recv处,直到读缓冲区有了数据可以读了为止。这里的阻塞与否主要是socket意义上的。总的来说,阻塞是个容易理解的概念。 而异步这个概念,比较泛,不好谈。最广义的异步可以通过同步来模拟,如果如果,则如何,否则如何,这其中的“则如何”不同需要关心何时会“如果”。多路复用一种很经典的程序结构,就是把线路给Selector,Selector来告诉用户程序那些线路可以进行IO。select/poll/epoll/kqueue都可以作为Selector。其中select因为是轮询的,效率较差。而epoll是基于事件通知的,效率不错。使用epoll,无论是多个进程,还是多个线程,理论上效能都一回事,实际和linux的进程、线程调度有关系,和用户程序质量也有关系。使用epoll,监视IO的可读写性的工作交给了系统,而真正的数据搬运,用户程序自己来。正因为如此,我们不能说epoll是AIO,两者基本扯不上关系。当然,epoll可以帮助编写一套广泛意义上的AIO套件,比如epoll等到读写事件,就把活交给一个IO线程去办,办完再通过该套件自己的事件机制向用户发通知说我办完了。虽然这样多扰了几层,但一定程度还是符合AIO的定义的。 说这些,是想说我对IO模型的理解并没有多少偏差。我的观察是,大多数人用epoll就实现了高性能并发的需求,Linux虽然实现了一系列aio_*,但没多少人去用。而AIO好像并非是性能的终极方案。 |