LWN: 最新的I/O带宽仲裁算法io.weight

640点击上方蓝色字关注我们~



The io.weight I/O-bandwidth controller

By Jonathan Corbet
June 28, 2019

kernel有个职责是要对所有对硬件资源的访问进行仲裁,确保每个进程都能得到公平对待。所谓的公平,是指根据系统管理员定义的策略、比例。一个主要需要管理的资源就是存储设备的I/O bandwidth。假如没有采取公平的分配,那么一个拥有很多I/O操作的进程很有可能会占满存储设备的全部带宽,导致其他进程抢不到资源。很多年来Kernel一直有几个I/O-bandwidth控制策略,效果上来说从来不能让所有人满意。不过近来提出的一个新的块设备控制方案可能能解决这个问题。


首先,I/O-bandwith controller面临着很多挑战。有些进程需要能确保他们对某个设备的最少访问带宽要永远得到满足。不过近来更多情况下大家更关注latency(延迟):进程需要能确保它的各个I/O访问要能够在某个给定标准时间之内完成。因此控制策略就需要能在满足这些需求的情况下,还要让对外设的访问能尽量达到最快。当然,外设各有不同特点,所以这个controller必须要能够满足各种类型设备上的操作优化需求。


最早的I/O-bandwidth controller允许管理员能对每个cgroup设置不同的带宽限制。不过缺点就是会导致哪怕外设还没有跑满的情况下也有可能会限制某些进程的I/O,客观上说浪费了I/O bandwidth。后期的io.latency controller更关注I/O latency,不过正如作者Tejun Heo所说,这个controller仅仅保护了那些对latency最敏感的进程,为此甚至可能会损害其他进程。他打算建立一个机制能够改善I/O bandwidth对各个cgroup的分配。


io.weight

新的controller通过给每个cgroup分配不同的weight值(权重)来实现。假设一个最简单的架构如图所示,如果对某个特定的block device来说,group A的访问权重是100,而group B的权重是300,那么B就可以占用75%的总带宽。权重的绝对值并不重要,主要是根据权重占同一级别对象的权重总值的比例来决定占带宽的比例。


这样就有一个问题,controller怎么能确定每个cgroup使用了多少带宽。简单的对I/O操作或者带宽进行统计并不是一个合适的方法,因为有些操作可能会比其他操作更加耗时。所以新的controller里使用了“cost model”来试图更好的估计具体各个request所占用的设备时间。这个模型相对比较简单。首先判断这个request是顺序访问还是随机访问。前者的话,这个操作能够更快的完成(特别是在机械硬盘的场景里)。根据判断结果会给这个操作赋予一个固定的启动耗时,还有会针对单位page的传输来累计增加耗时。最后算出来的就是这个request估计会需要执行的时长。

640

这个controller会观察各个外设的行为,来估算出上述这些耗时参数应该缺省设置为多少。系统管理员也可以通过在cgroup目录的io.weight.cost_model文件写入一些配置来更改这些参数。对每个外设可以指定最大的带宽值,以及每秒钟能完成的顺序访问或者随机访问的最大个数。read和write操作也可以分配不同的耗时值。


缺省的cost model应该也能工作的很好了。不过如果某些情况下这个模型工作的不够好,那么就可以通过eBPF来动态挂上一段代码更改这些耗时值的计算逻辑。


vtime

这个controller的底层实现,是通过为每个外设配置一个虚拟的时间(称为vtime)来做的。这个时间通常会每秒钟走1秒。而每个cgroup也有一个vtime时间,用来判断什么时候可以提交下一个I/O操作了。当算出每一个I/O操作的耗时之后,就可以加到这个group的vtime上去。只有当设备的vtime要比group的vtime走的快的时候才可以真正对外设发起这个I/O操作。每个group分配的weight权重决定了对每个操作的耗时乘以什么倍数。如果group A有25%的带宽分配,那么它的各个操作都会被乘以4。这样一来,各个cgroup就会呆在不同时间流速的宇宙里了,其中权重低的group的clock会走的更加慢。


为了避免device在空闲时某些I/O操作仍被限制不能访问设备,controller会做一些记录,记下哪些group没有用满它所分配到的全部带宽,然后暂时降低group的权重来跟它真实情况对应起来。效果上来说,这就会把空闲未分配的带宽借给其他想要I/O操作的进程了。也实现了一种机制能够让这个group在需要的时候,把它借出去的带宽快速抢回来。


剩下还有一个小问题:vtime机制设计用来确保发出的I/O request是按照外设能够处理的速度来发。不过cost model这个模型很可能不是100%精准的,并且某个设备的性能还可能会随着时间变化来变化。假如把cost model关掉,那么controller可能会发出过多的I/O request(导致latency增高),或者过少的request(导致带宽没有用满)。这些都是一些需要避免的情况。


那么controller如果发现request-completion的耗时不断增长,它就会认为发出去太多request了。这种情况就需要让这个忙过头的外设的vtime走得更慢一点,这样request发出去的速度能更慢。类似的,如果外设还有空闲,就需要让它的vtime走得更快一些,能发出更多request。


这个controller能自动调整这些速度,不过对某些场景可能并不是最合适的。对于write operation写操作来说,可能在设备内部排队,然后设备自己决定先完成哪个request,也就是说对每个reqeust来说,它的完成时间没法完全控制住。如果某些场景下必须要保证完成速度,那就需要更激进的降低request的发送速度,从而减少latency。当然可能带来的负面影响就是没法充分利用所有带宽了。cgroup目录里还有一个控制节点名叫io.weight.qos,这是用来设置预期的latency范围是多少,以及设备的vtime在多大程度上受latency范围的影响。


可以参考patch开头的描述来了解各个控制节点的作用。https://lwn.net/ml/linux-kernel/20190614015620.1587672-9-tj@kernel.org/


Heo认为缺省的参数已经表现很好了,至少对read request来说是这样的。如果有很多write操作,那么可能需要调整一下这些参数来得到最好的结果。相关的工具和文档(供系统管理员调整参数时使用)今后会提供,目前patch还没有太多反馈,毕竟是在6月13日才刚刚发布出来。乐观的说可能Linux 5.3里会包含这个功能,希望很快merge window到了的时候能通过review。


全文完

LWN文章遵循CC BY-SA 4.0许可协议。

极度欢迎将文章分享到朋友圈 
热烈欢迎转载以及基于现有协议上的修改再创作~


长按下面二维码关注:Linux News搬运工,希望每周的深度文章以及开源社区的各种新近言论,能够让大家满意~


640?wx_fmt=jpeg

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值