我之前的一篇文章《异步IO一定更好吗?》中举了一个很变态的例子,用以说明在单碟机械式硬盘上异步IO反而可能降低性能的问题,大家的讨论很热烈。前天的NodeParty杭州站分享会上,来自上海的@老赵 随口带出了这个问题,大概说是多个异步IO请求会使得性能提高,因为磁头走到哪里就处理到哪里,很多请求在“路上”就可以被处理掉了。
乍一看,我和老赵的结论是相反的。所以从nodeparty回来后查了查资料,并且做了一些实验,发现这两种情况在各自特定的场景里都可能是正确的,在别的场景又都可能是错误的。为什么呢?
我之前的结论没有认真考虑操作系统对IO调度的优化,对此一知半解就拿出来大放厥词,实在不应该!
Linux2.6内核对IO调度提供了四种算法:Completely Fair Queuing(CFQ)、Deadline、NOOP和Anticipatory(as),详细情况请点击这里阅读。在2.6内核中,系统默认的IO调度算法是CFQ,也就是OS会对请求的偏移量首先进行排序,按照这个排序顺序进行磁头的移动和请求响应,这正是老赵的观点的出处。而假如某个磁盘采用了NOOP的IO调度算法,也就是说内核不会对IO调度做任何优化,容易理解,正是我在《异步IO一定更好吗?》一问中的观点。除此之外,用户还可以为不同磁盘指定不同的IO调度算法。查看某个磁盘的IO调度算法的命令如下:
$[pengchun]$ cat /sys/block/sda/queue/scheduler
noop anticipatory deadline [cfq]
总结我的几点经验:
1. 异步IO不一定是性能最好的;
2. 操作系统对磁盘IO的各种调度算法中,没有哪一个是绝对更好的;随着应用场景的不同,很可能某一个算法的性能远远好于其他几个;而在另外的场景中则相反。例如,某个磁盘专门用来写日志的,那么你用NOOP就最好了;而如果要作为数据库的磁盘来使用,deadline可能是最好的算法了;
3. 尽管操作系统会做这样那样的优化,但不要懒惰地依赖操作系统;对机械式磁盘的访问,尽可能把随机访问变成顺序访问。