修改Linux的I/O调度器可以通过修改/sys/block/device/queue/scheduler来完成,有效选项
可以是as cfq deadline 和 noop,下面将介绍这几种调度器。

这个I/O调度器有什么用

先告诉大家一个数据,单次硬盘寻址平均需要8毫秒以上,但却是CPU周期的2500万倍。

为了解决硬盘与其他设备之间的巨大差异,便通过I/O调度器的基本功能 合并排序
来尽量减少磁盘寻址次数和移动距离(因为这是I/O中耗时最久的)。

改进读请求

每次读请求必须返回最新的数据因此,当请求的数据不在页缓存中时,读请求在数据从硬盘读出前会
一直阻塞–这可能是一个相当漫长的操作。我们将这种性能损失称为读延时

读请求之间存在依赖,打开这个文件可能需要先打开另外一个文件,这么样的话,我们可能需要硬盘再转一圈去寻址,
这样的话,读延时就太严重了。

因此最先想到的解决方法就是对这些寻址进行排序,让磁头的移动距离最小。

但是这样又出现了另一个问题,还是依赖的问题。在将寻址排序后,假如新的请求都是50 ~ 60之间的,
但是存在一个依赖需要访问第109块,这样的话,读延时会很严重,会极大影响系统性能。

Deadline

  1. 读写请求分离,读请求具有高优先调度权,除非写请求即将被饿死的时候,才会去调度处理写请求。这种处理可以保证读请求的延迟时间最小化。
  2. 对请求的顺序批量处理。对那些地址临近的顺序化请求,deadline给予了高优先级处理权。例如一个写请求得到调度后,其临近的request会在紧接着的调度过程中被处理掉。这种顺序批量处理的方法可以最大程度的减少磁盘抖动。
  3. 保证每个请求的延迟时间。每个请求都赋予了一个最大延迟时间,如果达到延迟时间的上限,那么这个请求就会被提前处理掉,此时,会破坏磁盘访问的顺序化特征,回影响性能,但是,保证了每个请求的最大延迟时间。

Anticipatory

还是寻址时间的问题。假设应用突然提交一个读请求,而且该请求即将到截止时间,I/O调度器响应该请求,
在硬盘中查找请求的数据,然后返回,再处理队列中其他请求。

这么做,会有很多次的硬盘寻址次数,而硬盘寻址又是非常耗时的,为了减少硬盘寻址次数,可以让
调度器在处理完一个读请求后稍微等待一下,如果还有读请求就一起处理;相比于硬盘寻址的时间,
调度器等待的时间是非常值得的。

这个anticipatory调度器的工作原理也叫做 预测,每处理完一个读请求后会等待6毫秒,
因为大部分读是相互依赖的,预测可以节省大量时间。

CFQ

Complete Fair Queuing I/O 调度器和前两种调度器目的是一致的。使用CFQ时,每个进程都有自己
的队列,每个队列分配一个时间片,同时还是存在着预测;在没有请求处理时会空转一段时间(默认10毫秒);在进程队列中同步请求(如读操作)被赋予比非同步请求更高的优先级。

Noop

Noop I/O调度器是最简单的调度器,它不排序,只简单的合并,一般使用在不需要对请求排序的
特殊设备上,也更快。

固态驱动器比机械硬盘快的原因

前文提到的不需要对请求排序的就是这种固态驱动器(SSDs)它使用类似随机访问内存的方式来索引,
没有硬盘的”旋转”代价。

参考源