一文搞懂新型IO调度器BFQ简介

2023-11-11 14:50

本文主要是介绍一文搞懂新型IO调度器BFQ简介,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Linux io调度器有很多种,大多数调度器都经受住了各种市场环境的长时间验证,稳定性、性能得到各种用户的认可,但新的调度器依然展露头角,在4.12内核中出现了一个新的bfq调度器,这个调度器将取代曾经的辉煌的cfq调度器。社区对待大的改动都是很谨慎的,为什么社区最终接受未经市场考验过的bfq调度器呢,本文结合bfq代码对此做个介绍。

一、bfq是什么

bfq全称Budget Fair Queueing,是Paolo Valente在2010年提出的一个IO调度器,目标是取代cfq。这里的“Budget”是指磁盘扇区sector,“Budget Fair”是指存储设备公平地对待每个进程,为各个进程服务相同数量的sector。图1描述了bfq的内部逻辑,这张图可以快速了解bfq调度器的特点。

图1 BFQ 逻辑图

图片引用自《High Throughput Disk Scheduling with Fair Bandwidth Distribution》

  1. 实线箭头代表IO请求的路径方向。这与其他的调度器一样,都是通过add_request类函数,将IO请求插入到进程的IO队列中,然后通过调度器的调度,由 dispatch函数下发到驱动处理。
  2. 虚线箭头代表bfq特有的budget特性。每个进程被分配了一定数量的budget,当该进程被bfq选择执行io时,最多只能访问这么多个budget。没访问一个sector,budget减1,budget用完了,bfq就会选择其他的进程执行io。执行io请求的进程由于某种原因过期时(budget用完了是一种原因),会基于上一次用了多少个budget重新估算下一次的budget数量。
  3. “Next active application selection”逻辑是每个IO调度器都有的核心功能,bfq中的这个功能与其他调度器不一样,其他的调度器会在系统中所有的IO队列中选择一个调度执行,而bfq只会在“eligible”属性的IO队列中选择一个调度执行(“eligible属性队列集”是“系统所有IO队列集”的子集),bfq的这个特性非常重要,是后面提到的bfq优势的理论基础。

二、bfq优势

调度器的设计离不开两个核心指标:高吞吐量、快速响应,但这两个指标是矛盾的,如何平衡这两个指标成了调度器首先要考虑的事。

bfq通过Budget based Worst-case Weighted fair Queueing (b-wf2q+)算法尽可能地最优化这两个指标,自动识别出batch类进程、交互式进程,确保交互式进程快速响应的前提下,尽可能地保证batch类进程的高吞吐量。

我们测试了有后台负载的情况下(3线程读,1线程写)冷启动高德地图的时间,在4个测试的调度器中,bfq表现最优。

(测试命令:Hikey-Tester.sh-sched noop/none/cfq/bfq -r 3 -w 1)

图2 高德地图冷启动时间

另外,在不同的负载模型下(10个随机读10r-rand,10个顺序读10r-seq,5个随机读5个随机写5r5w-rand,5个顺序读5个顺序写5r5w-seq)bfq的吞吐量优于或基本持平其他调度器。

图3调度器吞吐量

 资料直通车:Linux内核源码技术学习路线+视频教程内核源码

学习直通车:Linux内核源码内存调优文件系统进程管理设备驱动/网络协议栈

三、bfq优于其他调度器的原因

没有什么黑科技,原因有3个:

1)简单的“budget fair”策略(主要原因)

bfq选择进程执行io,有的进程只需少量的budget就能完成数据需求,有的进程则需要大量的budget才能完成数据需求,对于只消耗了少量的budget进程,必须频繁调度该进程才能保证它的budget公平。因交互式进程只需少量的budget,所以该策略可以保证交互式进程的快速响应特性。

每个进程被调度执行io时,有一个budget变量控制该进程最多能访问多少磁盘sector,每当进程访问了一些sector,budget就减去相应的sector数值,如果budget为0,该进程expire,bfqq选择新的进程执行io。

2)权重管理(辅助原因)

进程权重越大,budget增长越慢(意味着调度更频繁)。

3)新进程权重临时提升(辅助原因)

新进程创建时,短时间内会有大量IO请求,比如加载lib库、读写配置文件等等,临时提升权重有助于让新进程能有更多的时间访问存储设备,从而加快进程启动速度。

4)deceptive idleness(辅助原因)

进程发送一个同步io请求后,需要等待该io完成,才能发送下一个io请求。如果在等待期间,将当前进程expire掉,然后执行其他进程的io,这会影响当前进程的吞吐量。bfq的做法是同步io发送后,等待一小段时间Twait,看看有没有新的io到来。

结合代码对上述几点做个说明,bfq的算法伪代码如下:

1)add request将request插入到bfq中

line1~2每个进程都有一个bfq队列,一个时刻只有一个进程占有存储设备的使用权,这个进程叫做active_appl。首次成为active_appl的进程,被分配了一个remaining_budget,表示该进程还允许访问多少个磁盘sector。进程访问磁盘N个sector后,remaining_budget需减去N,当remaining_budget=0时,bfq将选择新的进程做为active_appl。

line 5~18 将request插入到第i个进程的队列中appl.queue。

如果appl.queue是空队列(两个可能:第1,已经不是active状态;第2,队列正处于deceptive idleness,等待下一个请求的到来,是active状态)需要做一些处理。若appl不是active_appl,调用b−wf2q+_insert插入bfq调度器红黑树管理结构中,若appl处于deceptive idleness状态,停止定时器计时。

2)dispatch request分发request给驱动处理

line24~38 当前active_appl的remaining budget小于即将处理的next req的大小,说明当前active_appl已经用完了分配给它的budget,需要更新相关状态并重新插入到bfq管理结构中。

line27~28 更新进程的vfinishtime,算法很简单,简单地对vfinishtime做个增长,增长值为基于权重、实际访问的磁盘sector数算出的一个虚拟值。该策略确保权重大的进程vfinishtime小,能够被调度的更频繁。

line30~34 由于该进程是用完了分配给它的budget,说明这次分配的budget少于实际需求,下一次需要分配更多的budget,代码中按BUDG INC STEP做了增量,但最大值不能超过active_appl.max_budget。该策略确保batch类进程每次处理较大的数据量,保证高吞吐需求。

line39~43 选择一个新的active_appl。

line45~49 选择下一个要处理的request,并将remaining budget值减去next_request.size。

line50~51 处理deceptive idleness场景,设置一个定时器,等待Twait时长。该策略确保连续发送同步io进程的吞吐量不下降。

line54 更新系统以及服务的budget数量。

line56 返回request,这个request即将被驱动处理。

3)b−wf2q将进程队列插入到bfq管理数据结构

V是存储器件累计访问的budget数,任何进程访问了磁盘sector,都会增加V,比如访问了n个sector,那么V = V + n。

进程的appl.F(bfq中叫finish time)会根据权重对实际访问的sector数量做个转换,作为该进程本次增长的budget数量。

进程的appl.S(bfq中叫做start time)一般情况下等于appl.F(这是一种简单的近似方法,如果用精确的方法,bfq作者认为太复杂)。

如果appl.S < V,那么这个进程是eligible属性,bfq会在eligible属性的进程中选择一个执行io。

四、结语

bfq的主算法思想极其简单:一个进程被调度执行,如果消耗完了分配给它的budget,那么就增加下一次的budget数量,反之则减少,类似于一个自适应算法。

bfq代码中还有很多trick,比如权重提升机制,peak rate估算方法等等,这许多机制使得bfq能够适应各自复杂的场景。

目前google chrome,Fedora等大公司已经在采用了bfq,预计一两年后会有越来越多的公司采用bfq调度器。

 

这篇关于一文搞懂新型IO调度器BFQ简介的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/390836

相关文章

JAVA线程的周期及调度机制详解

《JAVA线程的周期及调度机制详解》Java线程的生命周期包括NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING和TERMINATED,线程调度依赖操作系统,采用抢占... 目录Java线程的生命周期线程状态转换示例代码JAVA线程调度机制优先级设置示例注意事项JAVA线程

一篇文章让你彻底搞懂Java中VO、DTO、BO、DO、PO

《一篇文章让你彻底搞懂Java中VO、DTO、BO、DO、PO》在java编程中我们常常需要做数据交换,那么在数据交换过程中就需要使用到实体对象,这就不可避免的使用到vo、dto、po等实体对象,这篇... 目录深入浅出讲解各层对象区别+实战应用+代码对比,告别概念混淆,设计出更优雅的系统架构!一、 为什么

一文详解Java常用包有哪些

《一文详解Java常用包有哪些》包是Java语言提供的一种确保类名唯一性的机制,是类的一种组织和管理方式、是一组功能相似或相关的类或接口的集合,:本文主要介绍Java常用包有哪些的相关资料,需要的... 目录Java.langjava.utiljava.netjava.iojava.testjava.sql

一篇文章彻底搞懂macOS如何决定java环境

《一篇文章彻底搞懂macOS如何决定java环境》MacOS作为一个功能强大的操作系统,为开发者提供了丰富的开发工具和框架,下面:本文主要介绍macOS如何决定java环境的相关资料,文中通过代码... 目录方法一:使用 which命令方法二:使用 Java_home工具(Apple 官方推荐)那问题来了,

一文解析C#中的StringSplitOptions枚举

《一文解析C#中的StringSplitOptions枚举》StringSplitOptions是C#中的一个枚举类型,用于控制string.Split()方法分割字符串时的行为,核心作用是处理分割后... 目录C#的StringSplitOptions枚举1.StringSplitOptions枚举的常用

一文详解Python如何开发游戏

《一文详解Python如何开发游戏》Python是一种非常流行的编程语言,也可以用来开发游戏模组,:本文主要介绍Python如何开发游戏的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下... 目录一、python简介二、Python 开发 2D 游戏的优劣势优势缺点三、Python 开发 3D

Java Docx4j类库简介及使用示例详解

《JavaDocx4j类库简介及使用示例详解》Docx4j是一个强大而灵活的Java库,非常适合需要自动化生成、处理、转换MicrosoftOffice文档的服务器端或后端应用,本文给大家介绍Jav... 目录1.简介2.安装与依赖3.基础用法示例3.1 创建一个新 DOCX 并添加内容3.2 读取一个已存

Linux五种IO模型的使用解读

《Linux五种IO模型的使用解读》文章系统解析了Linux的五种IO模型(阻塞、非阻塞、IO复用、信号驱动、异步),重点区分同步与异步IO的本质差异,强调同步由用户发起,异步由内核触发,通过对比各模... 目录1.IO模型简介2.五种IO模型2.1 IO模型分析方法2.2 阻塞IO2.3 非阻塞IO2.4

一文详解MySQL索引(六张图彻底搞懂)

《一文详解MySQL索引(六张图彻底搞懂)》MySQL索引的建立对于MySQL的高效运行是很重要的,索引可以大大提高MySQL的检索速度,:本文主要介绍MySQL索引的相关资料,文中通过代码介绍的... 目录一、什么是索引?为什么需要索引?二、索引该用哪种数据结构?1. 哈希表2. 跳表3. 二叉排序树4.

Java中最全最基础的IO流概述和简介案例分析

《Java中最全最基础的IO流概述和简介案例分析》JavaIO流用于程序与外部设备的数据交互,分为字节流(InputStream/OutputStream)和字符流(Reader/Writer),处理... 目录IO流简介IO是什么应用场景IO流的分类流的超类类型字节文件流应用简介核心API文件输出流应用文