6.4. 配置
首先要决定使用那个 I/O 调度程序。本小节提供主要调度程序概述以帮助您确定最适合您的负载的那一款。
6.4.1. 完全公平调度(CFQ)
CFQ 尝试根据启动 I/O 的进程决定公平的 I/O 调度。可提供三个不同的调度等级:实时(RT),最佳效果(BE)和闲置。可使用
ionice
命令手动分配调度等级,或者使用 ioprio_set
系统调用编程分配。默认情况下将进程设定为最佳效果调度等级。在实时调度等级和最佳效果调度等级中有分为八个 I/O 优先级,其中 0 代表最高优先权,7 代表最低优先权。采用实时调度等级的进程比采用最佳效果和闲置等级的进程会被更频繁地调度,因此所有调度的实时 I/O 都要在最佳效果或者闲置 I/O 前执行。这意味着实时优先权 I/O 可耗尽最佳效果和闲置等级。最佳效果调度是默认调度等级,且给等级中的默认优先权为 4。停滞调度等级中的进程只有在系统中没有其他等待处理的 I/O 时才会执行。因此请记住只有在进程 I/O 完全不需要向前进行时方可将进程调度等级设定为闲置。
CFQ 通过为每个执行 I/O 的进程分配时间片段提供公平。在其时间片段中,进程每次最多可有八个请求(默认)。调度程序会尝试根据历史数据估计某个程序是否会在近期发出更多 I/O,然后 CFQ 会闲置,等待那个 I/O,即使有其他进程正在等待发出 I/O。
由于 CFQ 执行的闲置操作通常并不适合哪些不会受大量查询惩罚(seek penalty)影响的硬件,比如快速外置存储阵列或者固态硬盘。如果要求在此类存储中使用 CFQ(例如:如果您还喜欢使用 cgroup 加权 I/O 调度程序),则需要调节一些设置以改进 CFQ 性能。请在
/sys/block/device/queue/iosched/
中同一名称的文件中设定以下参数:
slice_idle = 0 quantum = 64 group_idle = 1
将
group_idle
设定为 1 后,可能会产生 I/O 停止(而由于闲置后端存储并不繁忙)。但这些停止的情况并不比系统队列中的闲置情况出现得频繁。
CFQ 是非工作守恒(non-working-conserving)I/O 调度程序,就是说即使在有等待处理的请求时也可以闲置(如前所述)。非工作守恒调度程序栈可在 I/O 路径中产生很大延迟。此类栈的示例为在基于主机的硬件 RAID 控制器顶层使用 CFQ。该 RAID 可部署其自身的非工作守恒调度程序,因此可在该栈的两级中造成延迟。非工作负载调度程序可在有尽可能多的数据供其做决定时操作最佳。在使用该调度算法的栈中,最底层的此奥读程序只能看到上层调度程序发送的数据。因此底层看到的 I/O 模式并不完全代表实际负载。
可调参数
back_seek_max
- 反向查询通常对性能有负面影响,因为它比正向查询标头重置时间要长很多。但如果负载较小,则 CFQ 仍执行此查询。这个可调参数以 KB 为单位控制 I/O 调度程序允许反向查询的间距。默认为
16
KB。 back_seek_penalty
- 由于反向查询的效率低,每项反向查询都有惩罚与之关联。惩罚是一个乘数。例如:视磁头位置在 1024KB。假设在队列中有两个请求,一个在 1008KB,一个在 1040KB。这两个请求到当前磁头位置登距。但如果应用反向查询惩罚(默认:2),则磁盘中距离较远的请求现在与较近的请求的距离缩短了一倍。因此磁头将向前移动。
fifo_expire_async
- 这个可调参数控制异步(缓存写入)请求等待的时间长度。过期后(以毫秒计)会将无法满足的异步请求移动到调度表中。默认为
250
毫秒。 fifo_expire_sync
- 这个参数与 fifo_expire_async 相同,用于同步请求(读取和 O_DIRECT 写入)。默认为
125
毫秒。 group_idle
- 设定后,CFQ 会在最后一个进程 cgroup 中发出 I/O 后闲置。当使用加权 I/O cgroup 并将
slice_idle
设定为0
后将其设定为1
(通常用于快速存储)。 group_isolation
- 如果启用组隔离(设定为
1
),它可以吞吐量为代价提供组群间更强大的隔离。一般来说,如果禁用组隔离,则只为连续负载提供公平机制。启用组隔离则会为连续以及随机负载提供公平机制。默认值为0
(禁用)。详情请参考Documentation/cgroups/blkio-controller.txt
。 low_latency
- 启用低延迟后(设定为
1
),CFQ 会尝试为设备中每个发出 I/O 的进程提供最长 300 ms 的等待时间。禁用低延迟(设定为0
)可忽略目标延迟,这样就可允许系统中的每个进程获得全部时间片段。默认启用低延迟。 quantum
- quantum 参数控制 CFQ 每次向该存储发出的 I/O 数,主要是限制设备队列深度。默认情况下将其设定为
8
。该存储可能支持更深的队列深度,但增加quantum
还将对延迟产生负面影响,特别是有大量连续写操作的时候。 slice_async
- 这个可调参数控制分配给每个发出异步(缓存写入)I/O 的进程的时间片段。默认将其设定为
40
毫秒。 slice_idle
- 这个参数指定 CFQ 在等待进一步请求时应闲置的时间。红帽企业版 Linux 6.1 以及更早版本中的默认值为
8
毫秒。在红帽企业版 Linux 6.2 以及之后的版本中默认值为0
。这个 0 值可通过删除队列以及服务树层中的所有闲置提高外置 RAID 存储流量。但 0 值可降低内置非 RAID 存储的流量,因为它会增加查询总量。对于非 RAID 存储建议您将slice_idle
值设定在 0 以上。 slice_sync
- 这个可调参数专门用于发出同步(读取或者直接写入)I/O 进程的时间片段。默认值为
100
毫秒。