您查询的关键词是:nonblock磁盘文件

如果打开速度慢,可以尝试快速版;如果想更新或删除快照,可以投诉快照

百度和网页 https://blog.csdn.net/doraeimo/article/details/14004769 的作者无关,不对其内容负责。百度快照谨为网络故障时之索引,不代表被搜索网站的即时页面。
为什么用non-blocking的方式读写磁盘文件无意义? - 信言的笔记 - CSDN博客

为什么用non-blocking的方式读写磁盘文件无意义?

最近在阅读《构建高性能web站点》第3章,文末提到“用non-blocking方式读写磁盘文件是无意义的”。作者对原因的描述一笔带过,促使我写了这篇笔记。

要解释这个问题,先要厘清为什么用non-blocking方式读写socket效率更高

 

许多资料上说,面对大量socket连接,blocking的I/O方式较non-blocking方式更为低效:每个线程招待一个socket,在等待socket缓冲区就绪的过程中,始终处于blocked状态,这些闲置线程会占用内存资源并导致大量无谓的线程上下文切换云云。

这个解释虽然没错,但此前一直误导我——以为blocked是一种有别于休眠的线程状态,它是活动的(在run queue里,会被线程调度器分配时间片后空转),所以才会产生无谓的上下文切换。实则不然,在linux世界里,blocked是一种特殊的休眠状态,同样会被移出run queue,从而不会被线程调度器唤醒。

 

既然都是休眠,blocked状态怎么就低效了呢,上下文切换的开销又何从谈起?

原来这是socket的特性决定的:来自客户端的数据以流的方式源源不断陆续抵达缓冲区,哪怕是一小片,工作线程也会被立刻唤醒以便及时处理,完后再次休眠。

对于一些需要实时交互的应用,这么做是必要的;

而对于HTTP,一个完整请求较陆续抵达的数据片段而言显得块头很大,这意味着工作线程会被反复唤醒,干的只是通过系统调用把缓冲区的内容挪到了用户态内存。

完整请求就绪前的数据片段越多,上下文切换就越频繁,于是额外的开销就出来了。

(这就好比麦当劳点了份套餐,服务员让你到位子上等,一会儿薯条好了让你跑一趟;汉堡好了又让你跑一趟;可乐好了再让你跑一趟。而不是等套餐齐了一次性来取。想想如果是全家桶……)

 

反观non-blocking方式,派一个专用线程盯着一堆socket连接,负责在数据就绪前帮它们打理缓冲区,就绪时通知它们。

(就是配餐员干的活……)

 

小结一下,I/O分成两个阶段,一是等待文件描述符可用,二是真正的执行读写操作;

blocked的本质是IO线程在阶段一等待文件描述符就绪时的可中断休眠状态(对于linux来说,底层只有可中断的休眠状态和不可中断的休眠状态

对于磁盘文件,不会像网络数据那样陆续抵达,无论是否blocking,都至多经历一次休眠,于是non-blocking显得多此一举了。

 

注意:POSIX规范保证了磁盘的文件描述符始终是可读写的。

 

================分割线================

补充阅读如下:

1.为什么要有non-blocking?

 

非阻塞最初的意图就是为了解决C10K问题,参见:http://www.kegel.com/c10k.html

如果10K线程,分别等待消息(不占用CPU),就会不停的被唤醒消息,处理完又等待,大量唤醒开销不小,

线程栈内存占用(JVM缺省每线程1M)x10K=10G也是个大问题,如果要支持100K问题更大,还要加上buffer的内存占用。

 

 

 

2.引入non-blocking之后,虽然降低了工作线程的内存占用和上下文切换,但由于默认情况下网卡的中断总是绑定在一个CPU上,导致其上下文切换过频进而负载过高;如何均摊网卡中断提升多核CPU利用率,引出IRQ Affinity。

附上一篇浅显易懂IRQ Affinity:

http://www.vpsee.com/2010/07/load-balancing-with-irq-smp-affinity/

http://www.vpsee.com/2010/07/smp-irq-affinity/

 

3.既然non-blocking读磁盘文件无意义,java6里面怎么还提供了NIO读文件的渠道FileChannel呢?

引出zero-copy即mmap,因为服务器往往需要通过网络对外发送图片等静态文件(读文件为了发送,而非本地处理),作为提升性能的方式,FileChannel.transferTo()方法通过减少内核态和用户态内存间的拷贝,高效地把本地文件从网卡发送出去。

 

 

展开阅读全文

没有更多推荐了,返回首页