异步IO一定更好吗?

标签: 学习 性能测试 异步IO 性能 | 发表时间:2011-03-10 12:03 | 作者:pengchun Wolf
出处:http://cnodejs.org/blog

在长林的文章《nodejs异步IO的实现》中提到,NodeJS通过libeio来实现IO操作的异步化,而libeio采用多线程的方式来模拟异步操作。

这里我需要强调一个观点,异步IO虽然是NodeJS一个非常重要的特点,但异步IO并不总是最好的,其他语言也一样。我们来看这么一个例子:

在我的磁盘上有2个文件,我希望在一个程序里读取这2个文件,每次输出一个字符。请注意,我不要求一定要两个文件被交替着读取,也不要求一定要先读完一个再读另一个。

怎么样,貌似还没说到问题的实质。那么我们再分几种情况:

  1. “磁盘”是指我的机器上只有一块机械式硬盘,或者有多个硬盘,但被读取的两个文件位于同一块硬盘上;
  2. 被读取的文件位于不同的两个机械式硬盘上;
  3. 被读取的两个文件位于同一块固态硬盘(SSD)上。

如果你熟悉机械式硬盘的原理,我想已经明白我要说什么了。否则,我们继续往下看。我们知道,传统的机械式硬盘要读取某一个文件,首先要将磁头移动到某个位置(fseek)。这个过程是一个物理运动,所花的时间跟磁盘转速、磁头移动的距离有关。读取一个字节后,磁头顺便移动到紧挨着的下一个字节。我写了一段通过异步方式读取文件的测试代码如下:

var fs  = require('fs');

function test_stream_read(file, id) {
        var stream      = fs.createReadStream(file, {
                flags: 'r',
                encoding: 'utf8',
                mode: 0666,
                bufferSize: 1
        });

        var tag = "[ " + id + " ] ";
        stream.on('data', function(chunk) {
                console.log(tag + "data: " + chunk.trim());
        });

        console.log(tag + "start");
}

test_stream_read('/disk1/a.txt', 1);
test_stream_read('/disk2/b.txt', 2);

在上面的代码中,我用NodeJS的ReadStream来读取文件,设定的bufferSize为1,即每次读取一个字符。由于NodeJS异步IO的多线程方式,供测试的两个文件在程序逻辑上可以被并行读取。所以影响性能的关键就落在存储介质(磁盘)能否并行处理上了。

在第一个case中,由于两个文件位于同一块机械式磁盘上,一块磁盘的磁头只有一个,所以只能是顺序的。你会发现,这种情况下磁头在盘面上移来移去,大量时间花在物理运动上,性能不差才怪呢!在这个case里,你还不如让NodeJS阻塞着读文件呢!

而第二个case中,两个文件位于两块磁盘上,它们之间能互相独立的被操作,实际上落在单个磁盘上的读请求仍然是顺序读取,性能会较好。

第三个case你自己分析吧,我不多讲了。

总结一下:

  1. 哪种方式读文件,要根据你的硬件和应用特点来权衡,切忌盲从。我认为要考虑的几点包括:硬盘原理、多少个硬盘、文件放在几个文件上、一次读取多少个文件、文件的平均大小、读取的缓冲区大小。
  2. NodeJS的fs.read方法实际上用的也是ReadStream,只不过bufferSize被写死了,为64K。如果你的文件大小都小于64K,那么你可以简单地忽略上面啰嗦的一大堆文字了。但是,这个原理你得清楚。

关于这个话题,我希望有更多的讨论和测试代码。欢迎拍砖给我。

相关 [异步 io] 推荐:

linux异步IO浅析

- Sepher - kouu's home
知道异步IO已经很久了,但是直到最近,才真正用它来解决一下实际问题(在一个CPU密集型的应用中,有一些需要处理的数据可能放在磁盘上. 预先知道这些数据的位置,所以预先发起异步IO读请求. 等到真正需要用到这些数据的时候,再等待异步IO完成. 使用了异步IO,在发起IO请求到实际使用数据这段时间内,程序还可以继续做其他事情).

异步IO一定更好吗?

- Wolf - CNode社区
在长林的文章《nodejs异步IO的实现》中提到,NodeJS通过libeio来实现IO操作的异步化,而libeio采用多线程的方式来模拟异步操作. 这里我需要强调一个观点,异步IO虽然是NodeJS一个非常重要的特点,但异步IO并不总是最好的,其他语言也一样. 在我的磁盘上有2个文件,我希望在一个程序里读取这2个文件,每次输出一个字符.

linux AIO (异步IO) 那点事儿

- zffl - CNode社区
这时候进程至少会阻塞10次,而这可能会导致其他的上千个用户请求得不到处理,这当然是不能接受的.. Linux AIO 早就被提上议程,目前比较知名的有 Glibc 的 AIO   与 Kernel Native AIO. 我们用Glibc 的AIO 做个小实验,写一个简单的程序:异步方式读取一个文件,并注册异步回调函数:.

关于IO的同步,异步,阻塞,非阻塞

- smile - IT技术博客大学习
标签:  IO  非阻塞  同步  异步  阻塞.     上次写了一篇文章:Unix IO 模型学习. 恰巧在这次周会的时候,@fp1203 (goldendoc成员之一) 正好在讲解poll和epoll的底层实现. 中途正好讨论了网络IO的同步、异步、阻塞、非阻塞的概念,当时讲下来,大家的理解各不相同,各执己见.

物理IO与逻辑IO

- - 操作系统 - ITeye博客
IO性能对于一个系统的影响是至关重要的. 一个系统经过多项优化以后,瓶颈往往落在数据库;而数据库经过多种优化以后,瓶颈最终会落到IO. 而IO性能的发展,明显落后于CPU的发展. Memchached也好,NoSql也好,这些流行技术的背后都在直接或者间接地回避IO瓶颈,从而提高系统性能. 上图层次比较多,但总的就是三部分.

java nio和io的比较

- - 互联网 - ITeye博客
第一部分:简单介绍NIO.     服务器在合理时间内处理大量客户机的请求的能力取决于服务器使用I/O流的效率,同时为成百上千的客户提供服务的服务器必须能并发的使用I/O服务.     用Java语言写的服务器,由于其线程与客户机之比几乎是一比一,因而易受到大量线程开销的影响,其结果是即导致性能问题,又缺乏伸缩性.

C++之文件IO操作流

- Nanqi - 博客园-首页原创精华区
  前两节介绍了C++的IO流类库,标准设备IO操作流中部分预定义流对象的成员函数以及IO格式控制. 那今天我将继续介绍关于C++中的流操作内容——文件IO操作流fstream. 并会着重讲解C++是如何对文件进行操作的.   文件指存放在外部介质上的数据的集合. 大家都知道操作系统是以文件为单位来对数据进行管理的.

MySQL数据库的IO操作

- - haohtml's blog
         淘宝丁奇分享的PPT:MySQL数据库的IO操作,详细分享了四块的内容,并且告诉大家如何调整MySQL数据库IO操作相关的参数,给出了详细的选择策略,现替其整理成文章分享与此. 4.影响io行为的一些参数和选择策略. 一个简单的查询 select * from t where id>=(  select id from t where k1=100 limit 100000,1) limit 2;.

定位IO瓶颈的一些方法

- - Linux - 操作系统 - ITeye博客
IO瓶颈往往是我们可能会忽略的地方(我们常会看top、free、netstat等等,但经常会忽略IO的负载情况),今天给大家详细分享一下如何确认一台服务器的IO负载是否到达了瓶颈,以及可能优化、定位的点. 先来看一台典型的IO密集型服务器的cpu统计图:. 可以看到,CPU总使用率不高,平均1.3%,max到5.6%,虽然大部分都耗在了iowait上,但才百分之五左右,应该还没到瓶颈吧.

hadoop的IO和MapReduce优化参数

- - CSDN博客系统运维推荐文章
           在MapReduce执行过程中,特别是Shuffle阶段,尽量使用内存缓冲区存储数据,减少磁盘溢写次数;同时在作业执行过程中增加并行度,都能够显著提高系统性能,这也是配置优化的一个重要依据.            下面分别介绍I/O属性和MapReduce属性这两个类的部分属性,并指明其优化方向.