文件系统学习7——文件系统队列机制概述
前面几小节讲述linux文件系统是如何操作IO流的,本小节讲述文件系统的队列机制,主要集中在IO调度器这一层的队列调度上。
1、队列机制
linux中的队列机制主要发生在IO调度器这一层,首先给出IO调度器在整个IO栈的位置,如下图所示。它位于bio块层之下,硬件驱动层之上。pagecache刷新下来的数据会合成对应的bio,同一个任务的多个bio会下发到块层,进行IO调度。
在早期的linux系统中,抽象块层的IO调度由于底层硬件只支持单队列处理模式,因此均采用的是左图的单队列IO调度,只是内部的调度方法有所不同。但由于底层存储介质的不断更新,特别是SSD的出现,多硬件队列已经极为普遍,因此linux3.13之后,内核加入了新的队列机制,称为多队列机制,其主要思想是为每个核配置一个请求队列,从而均衡多核之间的负载,并减少对请求队列的锁竞争。
多队列机制应用的相关paper:http://kernel.dk/blk-mq.pdf
2、传统单队列机制
对于传统的硬件设备,由于一般是处理单通道,因此linux将此硬件实例化为一个请求队列,所有应用程序发送的IO请求将全部提交至该队列中,然后交由该队列进行相应的处理,例如合并,调度等。
问题:当不同的任务并发的执行,请求下发到块设备层时,由于只有一个请求队列,所有的任务在自己执行的时候都需要先去或得该请求队列的锁,执行完成后才能释放锁,这无疑导致了多个并行的应用程序在请求队列上存在锁竞争的问题,对于多通道的硬件来说是很大的性能瓶颈。
3、多队列机制
正式由于上述多队列存在锁竞争等问题,多队列被提出,其结构如下图所示:
多队列的主要思想是将单个请求队列的资源进行离散化,划分到不同的请求队列上,同时利用cpu多核的思想,不同的核处理不同的请求,从而提高并发的效率。
多队列主要分为两种:软件队列和硬件队列
软件队列:软件队列原则上可为每个cpu核配置一个处理队列,同样,在对应的每个软件队列中可进行请求调度,添加标记以及计数等功能。由于软件队列和核可以绑定,该核处理的请求可以直接发送到其对应的软件队列上,从而可避免单请求队列造成的锁竞争问题。
硬件队列:硬件队列主要负责与底层设备驱动的匹配,即存在多少个设备驱动,则配置对应数量的硬件队列。其将负责将来自软件队列的请求发送至驱动层。
软硬件队列绑定
软硬件队列通常可以进行如下三种绑定,绑定之后,对应软队列的数据将会下发到指定的硬队列上,独立执行各自请求。
- 软件队列数目>硬件队列数目:将两个或者多个软队列分配给一个硬件队列,在执行调度时,硬件队列将从所有关联的软件队列中提取请求。
- 软件队列数目<硬件队列数目:顺序映射
- 软件队列数目=硬件队列数目:一一映射
4、单队列和多队列性能测试
文献http://kernel.dk/blk-mq.pdf中给出了多队列机制的测试结果。结果如下:
在实际测试中,基于Multi-queue的快设备层能够取得接近最优话的性能。如下图所示,其中MQ表示Multi-queue块设备层,SQ表示传统的单队列情况, Raw表示最优化的情况。系统分别取1,2,4,8 sockets系统。底层设备采取空设备模拟来消除SSD的性能对测试的干扰。在软件队列和硬件队列配置上,每个core配置一个软件队列,每个socket配置一个硬件队列。
从实验结果中,我们可以发现,MQ能够取得极大的性能提升。
5、参考文献
https://blog.****.net/notbaron/article/details/81147591
https://hyunyoung2.github.io/2016/09/14/Multi_Queue/
https://blog.****.net/yedushu/article/details/82050933
https://blog.****.net/g382112762/article/details/53221272
http://kernel.dk/blk-mq.pdf