选择 Linux I/O 调度程序
Posted
技术标签:
【中文标题】选择 Linux I/O 调度程序【英文标题】:Selecting a Linux I/O Scheduler 【发布时间】:2010-11-03 19:40:51 【问题描述】:我读到可以通过写入 /sys/block/[disk]/queue/scheduler 来更改正在运行的内核上特定设备的 I/O 调度程序。例如我可以在我的系统上看到:
anon@anon:~$ cat /sys/block/sda/queue/scheduler
noop anticipatory deadline [cfq]
默认是完全公平的排队调度程序。我想知道在我的自定义内核中包含所有四个调度程序是否有任何用处。除非内核足够聪明,可以为正确的硬件选择正确的调度程序,特别是用于基于闪存的驱动器的“noop”调度程序以及用于传统驱动器的其他调度程序,否则编译多个调度程序似乎没有多大意义硬盘。
是这样吗?
【问题讨论】:
【参考方案1】:如/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)和其他非旋转介质(闪存)的最佳选择,因为尝试重新调度 I/O 会浪费资源
deadline
是一个轻量级调度程序,它试图对延迟施加硬性限制
cfq
试图维护系统范围内 I/O 带宽的公平性
很长一段时间默认是anticipatory
,它接受了很多调整,但在2.6.33(2010年初)中被删除。 cfq
不久前成为默认值,因为它的性能合理且公平是多用户系统(甚至单用户桌面)的一个很好的目标。对于某些场景——数据库经常被用作示例,因为它们往往已经有自己独特的调度和访问模式,并且通常是最重要的服务(那么谁在乎公平呢?)—— anticipatory
长期以来一直可以调整这些工作负载的最佳性能,deadline
非常快速地将所有请求传递到底层设备。
【讨论】:
很棒的信息,谢谢!但是我的基本问题仍然没有答案,如果我插入闪存驱动器或者我的上网本在闪存盘上运行,因为它的主驱动器是内核足够聪明,可以选择 noop 而不是默认的 cfq?还是完全由我手动完成? 您可以将内核配置为默认使用不同的调度程序。在非旋转媒体上自动使用noop
会很聪明,但内核没有该功能。它确实可以检测到非旋转介质,但它并不可靠,因为某些磁盘会误报自己,而且它还没有连接到 I/O 调度程序代码。
您可以添加 udev 规则来根据设备特性定义调度程序,如 debian wiki (wiki.debian.org/SSDOptimization#Low-Latency_IO-Scheduler) # 为非旋转磁盘设置截止时间调度程序 ACTION=="add|change", KERNEL=="sd[az]", ATTRqueue/rotational=="0", ATTRqueue/scheduler="deadline"
@Dani_l 您应该扩展它并将其添加为答案。
有没有办法在运行时同时为所有驱动器更改它?同样通过内核命令行参数“电梯”设置默认调度程序。谢谢。【参考方案2】:
您可以在启动时通过将“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
【讨论】:
我不明白为什么这个答案值得这么多反对。实际上并没有错。【参考方案4】:可以使用 udev 规则让系统根据硬件的某些特性来决定调度程序。 SSD 和其他非旋转驱动器的示例 udev 规则可能如下所示
# set noop scheduler for non-rotating disks
ACTION=="add|change", KERNEL=="sd[a-z]", ATTRqueue/rotational=="0", ATTRqueue/scheduler="noop"
在新的 udev 规则文件中(例如,/etc/udev/rules.d/60-ssd-scheduler.rules
)。此答案基于debian wiki
要检查ssd磁盘是否会使用该规则,可以提前检查trigger属性:
for f in /sys/block/sd?/queue/rotational; do printf "$f "; cat $f; done
【讨论】:
关于自动检测非旋转媒体并将 IO 调度程序仅应用于这些媒体的绝佳答案。不仅建议非旋转媒体使用截止日期。 Oracle 建议针对数据库工作负载使用截止时间 io 调度程序。这个 Oracle 的建议可能来自这样一个事实:deadline 可能比其他 IO 调度程序处理更好的同步写入。例如,查找 /sys/block/sdX/queue/iosched/writes_starved “deadline”调度程序可调参数(没有这样的读取可调参数)。如果数据库的同步重做写入没有快速完成,数据库的性能可能会很差。【参考方案5】:让内核支持不同的内核的目的是您可以在不重新启动的情况下试用它们;然后,您可以通过系统运行测试工作负载,测量性能,然后将其作为您应用的标准。
在现代服务器级硬件上,只有 noop 似乎完全有用。在我的测试中,其他的似乎较慢。
【讨论】:
你如何在运行时实际更改它? noop 相对于其他调度程序的性能很大程度上取决于硬件和特定负载。出于好奇,您正在运行哪些磁盘、控制器和测试? 是的,当您拥有智能 RAID 控制器和其他比内核更了解最佳访问模式的东西时,noop 是很好的选择。截止日期也不错。 这对我来说纯粹是一个学习练习,我正在尝试配置最小和最快的启动内核,以提供我在笔记本电脑上需要的所有功能。我查看了“Linux Kernel Development”和“Essential Linux Device Drivers”,并没有找到一个令人满意的答案,内核在运行时选择调度程序时有多聪明,或者它是否总是使用默认值,除非您手动将其设置为其他内容? ephemient > 在 DELL PERC 控制器上,也在 DELL Powervault MD3000 上。它似乎比两者的默认值 (CFQ) 都要好。以上是关于选择 Linux I/O 调度程序的主要内容,如果未能解决你的问题,请参考以下文章