专栏首页王小二的Android站[045][译]cfq-iosched.txt

[045][译]cfq-iosched.txt

前言

按照[043][译]blkio-controller.txt,我已经学会了如何通过cgroup v1来调整不同进程的IO权重,这个IO权重是在CFQ调度算法中实现的,在深入学习一下CFQ调度算法之前,我决定先看一下CFQ的说明书cfq-iosched.txt。翻译完这个文档之后,我感觉受益良多,比网上很多的资料讲的清楚多了。

cfq-iosched.txt

CFQ (Complete Fairness Queueing)完全公平排队
===============================
CFQ调度器的主要目的是为所有请求I/O操作的进程,提供请求磁盘的I/O操作的公平分配。

CFQ为请求I/O的进程维护每个进程队列操作(同步请求)。
在异步请求的情况下,所有进程的请求都根据其进程的I/O优先级。

CFQ调度器可调项
========================

slice_idle
----------
这指定CFQ在确定的CFQ队列上(对于顺序工作负载)的下一个请求应空闲多长时间
以及在队列过期之前,服务树(对于随机工作负载),CFQ选择要从中分派的下一个队列。

默认情况下,slice_idle是一个非零值。这意味着默认情况下我们在队列/服务树会空闲。
这对于单轴SATA/SAS磁盘等高稳定性介质非常有用,我们可以减少总的寻道次数,并提高吞吐量。

将slice_idle设置为0将删除队列/服务树上的所有空闲。在更快的存储上,例如硬件RAID配置中的
多个SATA/SAS磁盘等设备,我们应该看到总体吞吐量的提高。不利的一面是,写操作提供的隔离也会降低,
IO优先级的概念会变得更弱。

因此,根据存储和工作负载的不同,将slice_idle设置为0可能会很有用。
一般来说,我认为对于SATA/SAS磁盘和SATA/SAS磁盘的软件RAID,保持slice_idle开启应该很有用。
对于任何配置单个LUN(基于主机的硬件RAID),设置slice_idle=0可能会得到更好吞吐量和可接受的延迟的结果。

back_seek_max
-------------
这指定了以KB为单位,向后搜索的最大“距离”。
这个距离是从当前头部位置到在距离方面向后的扇区。

此参数允许调度器在后面方向中预测请求
如果他们在这个范围内,就把他们当作“下一个”与当前头部位置的距离。

back_seek_penalty
-----------------
此参数用于计算反向搜索的成本。如果请求的后向距离仅为“前”请求的1/back_seek_penalty,
则认为两个请求的搜索成本相等。

所以调度器不会偏向一个或另一个请求(否则调度器会偏向前请求)。
back_seek_penalty的默认值是2.

fifo_expire_async
-----------------
此参数用于设置异步请求的超时。
默认值是248ms。

fifo_expire_sync
----------------
此参数用于设置同步请求的超时。默认值是124ms. 
如果希望同步请求优于异步请求,则应当减少fifo_expire_sync这个值。

group_idle
-----------
此参数强制在CFQ组级别而不是CFQ队列级别的空闲。这是在观察到高端存储由于顺序队列上的空闲而出现瓶颈并
允许从单个队列进行调度后引入的。这个参数的思想是它可以在slice_idle=0和group_idle=8的情况下运行
,使空闲不会在组中的单个队列上发生,而是在组中整体发生,从而仍然保持IO控制器工作。

在组中的单个队列上不空闲,同时从组中的多个队列分派请求,并在更高端的存储上实现更高的吞吐量。

参数的默认值是8ms.

low_latency
-----------
这个参数被用于开启/关闭CFQ调度器的low_latency模式,
如果开启,CFQ将会尝试重新计算每个进程时间片,基于系统设置的low_latency。
这有利于公平而不是吞吐量。关闭low latency (设置成0) 忽略目标延迟,
将会允许系统中的每一个进程获得完整的时间片

默认low latency模式是开启的.

target_latency
--------------
这个参数用于计算每一个进程获得的时间片,在开启CFQ的latency模式。 
它将确保同步的请求有一个估计的延迟。 但是顺序工作更加重要(例如顺序读),
然后为了满足延迟限制,由于每个进程在交换cfq队列之前,发出I/O请求的时间减少,吞吐量可能会降低。

虽然这可以通过禁用latency_mode来克服,但它可能会增加某些应用程序的读取延迟。
此参数允许通过sysfs接口更改target_latency,该接口可以提供平衡的吞吐量和读取延迟。

默认值target_latency是300ms.

slice_async
-----------
此参数和slice_sync一样,但是只是用于异步队列
默认值是40ms.

slice_async_rq
--------------
这个参数用于限制异步请求分发到设备的请求队列,在队列中的时间片,允许分派的最大请求数也取决于io优先级。. 
默认值是2.

slice_sync
----------
当某个队列被选择执行的时候, 这个队列IO请求,只在一个确定的时间片里去执行,在切换到另外一个队列之前。
这个参数就是用于同步队列的时间片的计算

时间片的计算用以下方程式-
time_slice = slice_sync + (slice_sync/5 * (4 - prio)). 
为了增加同步IO的时间片,增加slice_sync的值 默认值100ms.

quantum
-------
这个参数指定了被转发到设备队列的数量. 
在一个队列的时间片中,如果转发给设备队列的数量超过了这个数,另一个请求将不会出现.
这个参数用户同步请求

如果存储有多个磁盘,此设置可以限制请求的并行处理。因此,增加该值可以提高性能,
尽管这可能会导致一些I/O的延迟由于请求的数量增加而增加


CFQ Group scheduling
====================
CFQ支持blkio cgroup,在每个blkio cgroup目录中有"blkio."前缀的文件。
它是基于权重基础,有四个旋钮对于配置-权重[_设备]和叶权重[_设备]。
内部cgroup节点(带有子节点的节点)也可以在其中包含任务,
前两个配置cgroup作为一个整体在其父级有权享有的比例,
后两个配置cgroup中的其直接子任务相比所占的比例。

另一种思考方法是假设每个内部节点一个隐式的叶子节点,它承载所有的任务,其权重为
叶权重[设备]配置。假设一个blkio层次结构由根、A、B、AA和AB五个cgroups组成
下面表示每个名称的权重。

        weight leaf_weight
 root :  125    125
 A    :  500    750
 B    :  250    500
 AA   :  500    500
 AB   : 1000    500

 根从来没有一个父母使其重量是毫无意义的。向后兼容性,权重始终与叶权重保持同步。
 B、AA、AB没有子代,因此它的任务没有子代与竞争。他们总是能得到cgroup在父级100%。
 仅考虑影响的权重,层次结构如下所示。

           root
       /    |   \
      A     B    leaf
     500   250   125
   /  |  \
  AA  AB  leaf
 500 1000 750

 如果所有的cgroup都有活动的IOs并且彼此竞争,那么磁盘时间将按如下方式分配:
 分布在根下。此级别的总有效重量为
 A:500 + B:250 + C:125 = 875.

 root-leaf :   125 /  875      =~ 14%
 A         :   500 /  875      =~ 57%
 B(-leaf)  :   250 /  875      =~ 28%

 A有孩子,并进一步将其57%分配给孩子隐式叶节点。
 此级别的总有效重量为
 AA:500 + AB:1000 + A-leaf:750 = 2250.

 A-leaf    : ( 750 / 2250) * A =~ 19%
 AA(-leaf) : ( 500 / 2250) * A =~ 12%
 AB(-leaf) : (1000 / 2250) * A =~ 25%

 组调度的CFQ-IOPS模式
 ===================================
 基本的CFQ设计是提供基于优先级的时间片。更高优先级进程的时间片越大,优先级越低进程的时间篇越短。
 如果存储速度快并且支持NCQ和最好在一次请求队列中,转发来自多个cfq队列的多个请求。
 在这种情况下,不可能精确测量被单个队列消耗时间。

 不过,可以测量从单个队列发出的请求数,同时允许从多个cfq队列发出,
 这就有效地提高了IOPS(IO operations per second)的公平性。

 如果设置slice_idle=0,并且存储支持NCQ,CFQ会在内部切换到IOPS模式,并根据分派的请求数提供公平性。
 注意,此模式切换仅对组调度有效。对于非cgroup用户,不应更改任何内容。

 CFQ-IO调度器空闲理论
 ===============================
 在队列中空闲主要是为了等待下一个请求的到来在同一队列上,在请求完成后之后。
 在此过程中,CFQ不会从其他cfq队列中分派请求,即使在处于挂起状态的请求在其他cfq队列。

 空转的基本原理是它可以减少旋转介质上的寻道次数。例如,如果一个进程正在执行相关的顺序读取
 (下一次读取仅在前一次读取完成后才开始),那么不从其他队列发送请求应该会有所帮助,
 因为我们没有移动磁盘头,而是继续从一个队列发送顺序IO。

 CFQ有以下服务树,并且在这些树上放置各种队列。
      sync-idle sync-noidle async

 所有执行同步顺序IO的cfq队列都将会到sync-idle树。
 在这棵树上,我们分别在每个队列上空闲。

 所有同步非顺序队列都在sync-noidle树上。还有任何未标记REQ_IDLE的同步写入请求在此进行服务树。
 在此树上,我们不在单个队列上空闲,而是在空闲在整个队列组或树上。所以如果有4个排队等候分派的IO,
 只有在最后一个队列分派最后一个IO后,我们才会空闲。

 所有异步写会到async服务树,不会有空闲在异步的队列

 CFQ对ssd进行了一些优化,如果它检测到一个支持更高队列深度的非旋转媒体(一次运行多个请求),
 那么它就减少了单个队列的空闲,所有队列都移动到同步noidle树,只剩下树空闲。
 此树空闲为异步树上的缓冲写队列提供隔离。

常见问题解答
 ===
 Q1. 为什么要在所有未标记REQ_IDLE的队列上空闲(树空闲)。
 A1. 我们只对未标记REQ_IDLE的队列执行树空闲(sync-noidle树上的所有队列)。
     这有助于为所有同步空闲队列提供隔离。否则,在存在许多顺序读的情况下,其他异步的IO可能无法获得公平的磁盘份额。
     
     举个例子,假如有10个顺序读正在处理IO,每拿到了100ms。如果一个非REQ_IDLE请求来了,他将会在1秒以后野蛮的
     调度。如果在非REQ_IDLE请求完成之后,我们不空闲,几毫秒后另外一个非REQ_IDLE请求来了,他将在再次在1秒之后
     被调度。重复的,注意一个工作负载如何丢失其磁盘共享并遭受损失,由于多个顺序读。

     fsync可以生成依赖的IO,其中一堆数据是在fsync的上下文中写入的,然后再写入一些日志数据。
     日志数据只有在fsync完成其IO(至少对于ext4来说是这样)之后才会出现。
     现在如果有人决定不空闲的fsync线程由于没有!REQ_IDLE,则下次日志写入将不会被安排为另一秒。
     如果一个进程执行的fsync很小,那么在有多个顺序读的情况下,这个进程将受到严重影响。

     因此在所有非REQ_IDLE的线程上执行树空闲,提供了与多个顺序读的隔离,同时我们不在单个线程上空闲。

 Q1. 何时指定REQ_IDLE
 A2. 我认为,当一个人正在进行同步写操作,并且希望很快从同一个上下文发送更多的写操作时,
     应该能够在写操作时指定REQ_IDLE,这可能在大多数情况下都能很好地工作。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • [007]一次Binder通信最大可以传输多大的数据?

    在第六章中,我通过匿名共享内存的方式解决Binder通信是无法传递大数据的问题,一次Binder通信最大可以传输是1MB-8KB(PS:8k是两个pagesiz...

    王小二
  • [021]MTP架构解析

    这两天正好在研究一个通过MTP模式拷贝文件到手机速度慢的问题,顺便把整个MTP架构学了一遍,所以写一篇文章记录并分享一下。

    王小二
  • [023]你真的懂AIDL的oneway嘛?

    用AIDL的人应该都知道下面代码中start和stop方法定义成oneway代表这个Binder接口是异步调用。

    王小二
  • IBM MQ运维使用手册

    操作系统版本:SUSE Linux Enterprise Server 10 SP4    32bit

    loong576
  • CKafka系列学习文章 - 什么是消息队列 ?(一)

    | 导语 在大家的工作当中,是否碰到大量的插入、更新请求同时到达数据库,这会导致行或表被锁住,最后会因为请求堆积过多而触发“连接数过多的异常”(Too Man...

    发哥说消息队列
  • Java中的 Threadpoolexecutor类

    在之前的文章Java中executors提供的的4种线程池中,学习了一下Executors类中提供的四种线程池.

    呼延十
  • 算法一看就懂之「 队列 」

    算法的系列文章中,之前咱们已经聊过了「 数组和链表 」、「 堆栈 」,今天咱们再来继续看看「 队列 」这种数据结构。「 队列 」和「 堆栈 」比较类似,都属于线...

    奎哥
  • RabbitMQ消息通信

    ---- 概述 RabbitMQ是一个开源的消息代理和队列服务器,用来通过普通协议在完全不同的应用之间共享数据或者将作业排队以便让分布式服务器进行处理。应用程序...

    BrianLv
  • 17 个方面,全面对比 Kafka、RabbitMQ、RocketMQ、ActiveMQ 各自的优缺点

    原文链接:http://t.cn/RVDWcfe

    业余草
  • 想了解Kafka,RabbitMQ,ZeroMQ,RocketMQ,ActiveMQ之间的差异?这一篇文章就够了!

    本文将从,Kafka、RabbitMQ、ZeroMQ、RocketMQ、ActiveMQ 17 个方面综合对比作为消息队列使用时的差异。

    搜云库技术团队

扫码关注云+社区

领取腾讯云代金券