选择一个Linux I/O调度器

86

我读到说可以通过写入/sys/block/[磁盘]/queue/scheduler 来改变正在运行的内核中特定设备的I/O调度程序。例如,我在我的系统上可以看到:

anon@anon:~$ cat /sys/block/sda/queue/scheduler 
noop anticipatory deadline [cfq] 

默认情况下是完全公平排队调度程序。我想知道是否有必要在我的自定义内核中包含所有四个调度程序。除非内核足够聪明以选择正确的调度程序适配正确的硬件,特别是将'noop'调度程序用于基于Flash的驱动器,并将其中一个调度程序用于传统硬盘,否则似乎没有必要编译多个调度程序。

是这种情况吗?

5个回答

111

/usr/src/linux/Documentation/block/switching-sched.txt中所述,任何特定块设备上的I/O调度程序都可以在运行时更改。在使用新调度程序之前,必须刷新之前调度程序的所有请求,可能会有一些延迟,但即使设备正在高负荷下也可以无问题地更改。

# cat /sys/block/hda/queue/scheduler
noop deadline [cfq]
# echo anticipatory > /sys/block/hda/queue/scheduler
# cat /sys/block/hda/queue/scheduler
noop [deadline] cfq
理想情况下,有一个单一的调度程序来满足所有需要。但目前似乎还没有这样的调度程序。内核通常无法具备足够的知识来选择最适合您的工作负载的最佳调度程序: - `noop` 经常是内存支持的块设备(例如ramdisk)和其他非旋转介质(flash)的最佳选择,在这些设备上尝试重新安排I/O是浪费资源。 - `deadline` 是一种轻量级调度程序,试图对延迟设置硬限制。 - `cfq` 尝试维护 I/O 带宽的系统范围公平性。
长时间以来,默认调度程序是 `anticipatory`,并且接受了很多调优,但在2.6.33(2010年初)中被删除。 `cfq` 已经成为默认设置一段时间了,因为其性能合理且公平性是多用户系统甚至单用户桌面的良好目标。对于某些场景 - 如数据库,它们倾向于已经拥有自己的特殊调度和访问模式,并且通常是最重要的服务(那么谁关心公平性?) - `anticipatory` 在这些工作负载上具有最佳性能的悠久历史,而 `deadline` 会迅速将所有请求传递到底层设备。

1
非常有用的信息,谢谢!但是我的基本问题仍然没有得到回答,如果我插入一个闪存驱动器或者我的上网本以闪存盘作为主要驱动器运行,内核是否足够聪明地选择noop而不是默认的cfq?还是完全由我手动决定? - Robert S. Barnes
3
您可以配置内核默认使用不同的调度程序。自动在非旋转介质上使用“noop”是明智的,但内核没有该功能。虽然它有一定探测非旋转媒体的功能,但由于某些磁盘误报自身信息,并且还未与I/O调度程序代码连接起来,因此不可靠。 - ephemient
8
您可以添加udev规则根据设备特性来定义调度程序,就像debian wiki中所述(https://wiki.debian.org/SSDOptimization#Low-Latency_IO-Scheduler) #为非旋转磁盘设置deadline调度程序 ACTION ==“add | change”,KERNEL ==“sd [a-z]”,ATTR {queue / rotational} ==“0”,ATTR {queue / scheduler} =“deadline” - Dani_l
@Dani_l 你应该扩展它并将其添加为答案。 - Robert S. Barnes
1
有没有一种方法可以在运行时一次性更改所有驱动器的设置?同样,可以通过内核命令行参数“elevator”设置默认调度程序。谢谢。 - SkyRaT
显示剩余2条评论

22

可以使用udev规则,根据硬件的某些特征让系统决定调度器。
例如,SSD和其他非旋转驱动器的udev规则可能如下所示:

使用udev规则可根据硬件特征自动选择调度器,例如针对SSD和其他非旋转驱动器的规则。

# set noop scheduler for non-rotating disks
ACTION=="add|change", KERNEL=="sd[a-z]", ATTR{queue/rotational}=="0", ATTR{queue/scheduler}="noop"

在新的udev规则文件内(例如/etc/udev/rules.d/60-ssd-scheduler.rules),可以添加以下内容。这个答案基于Debian wiki

如果要检查SSD磁盘是否使用该规则,可以事先检查触发属性。

for f in /sys/block/sd?/queue/rotational; do printf "$f "; cat $f; done

关于自动检测非旋转媒体并仅将IO调度器应用于这些媒体的出色答案。截止时间不仅适用于非旋转媒体。Oracle建议在数据库工作负载中使用deadline io调度程序。这个建议可能来自于deadline比其他IO调度程序更好地处理同步写入的事实。例如,在/sys/block/sdX/queue/iosched/writes_starved中寻找“deadline”调度程序可调整项(对于读取没有这样的可调整项)。如果同步重做写入未能快速完成,则数据库的性能可能会受到影响。 - Tagar

7

内核支持不同的目的在于您可以在不重新启动的情况下尝试它们;然后,您可以通过系统运行测试工作负载、测量性能,然后将其作为您的应用程序的标准。

在现代服务器级硬件上,只有noop似乎有用。其他的在我的测试中似乎更慢。


你如何在运行时实际更改它? - Robert S. Barnes
noop相对于其他调度程序的性能非常依赖于硬件和特定负载。出于好奇,您运行了哪些磁盘、控制器和测试? - ephemient
1
是的,当你有智能RAID控制器和其他一些东西时,noop是很好的选择,因为它比内核更了解最佳访问模式。Deadline也不错。 - Zan Lynx
1
这只是我进行的一个学习练习,我试图配置最小且启动最快的内核,以提供我在笔记本电脑上所需的所有功能。我已经查阅了《Linux内核开发》和《Essential Linux设备驱动程序》两本书,但没有找到令人满意的答案:内核在运行时选择调度程序有多聪明,或者它是否总是使用默认值,除非您手动将其设置为其他值? - Robert S. Barnes
ephemient > 这是在 DELL PERC 控制器上,也在 DELL Powervault MD3000 上使用的。它似乎比默认的 CFQ 在两者上都更好。 - MarkR
啊,真正的服务器级硬件。是的,我可以想象noopcfq表现更好,但deadline也应该相当不错... - ephemient

0

您可以通过在内核命令行中添加“elevator”参数(例如在grub.cfg中)来在启动时设置此项。

示例:

elevator=deadline

这将使 "deadline" 成为所有块设备的默认 I/O 调度程序。

如果您想在系统启动后查询或更改调度程序,或者想为特定的块设备使用不同的调度程序,我建议安装并使用工具ioschedset,使此过程变得简单。

https://github.com/kata198/ioschedset

如果你使用的是Archlinux,它可以在aur中找到:

https://aur.archlinux.org/packages/ioschedset

一些使用示例:

# Get i/o scheduler for all block devices
[username@hostname ~]$ io-get-sched
sda:    bfq
sr0:    bfq

# Query available I/O schedulers
[username@hostname ~]$ io-set-sched --list
mq-deadline kyber bfq none

# Set sda to use "kyber"
[username@hostname ~]$ io-set-sched kyber /dev/sda
Must be root to set IO Scheduler. Rerunning under sudo...

[sudo] password for username:
+ Successfully set sda to 'kyber'!

# Get i/o scheduler for all block devices to assert change
[username@hostname ~]$ io-get-sched
sda:    kyber
sr0:    bfq

# Set all block devices to use 'deadline' i/o scheduler
[username@hostname ~]$ io-set-sched deadline
Must be root to set IO Scheduler. Rerunning under sudo...

+ Successfully set sda to 'deadline'!
+ Successfully set sr0 to 'deadline'!

# Get the current block scheduler just for sda
[username@hostname ~]$ io-get-sched sda
sda:    mq-deadline

使用应该是不言自明的。这些工具是独立的,只需要bash。

希望这可以帮到你!

编辑:免责声明,这些是我编写的脚本。


-3

Linux内核不会在运行时自动更改IO调度程序。我的意思是,截至今天,Linux内核无法根据次要存储设备的类型自动选择“最佳”调度程序。在启动期间或运行时,可以手动更改IO调度程序。

默认调度程序是根据位于/linux-2.6/block/Kconfig.iosched文件中的内容在启动时选择的。但是,在运行时通过将有效的调度程序名称echo到/sys/block/[DEV]/queue/scheduler文件中可以更改IO调度程序。例如:echo deadline > /sys/block/hda/queue/scheduler


8
我不明白为什么这个答案会被投票踩得那么多。实际上它并不是错的。 - DepressedDaniel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接