今天看到一篇论文:Linux Block IO: Introducing Multi-queue SSD Access on Multi-core Systems 。 这篇论文发表于 2013 年,介绍 Linux 内核的 block layer 针对现代硬件——高速 SSD、多核 CPU(NUMA)的新设计。 总的来说,设计方案不难理解,并没有涉及什么牛逼或者新颖的内容。这里面提到的内容从 Linux 3.11 开始出现在内核,Linux 3.16 成为内核的一个完整特性[6]。Linux 5.0 开始成为 block layer 的默认选项[7]。
在此之前的 Linux block layer 应该是从 Linux 2.6 之后就没有怎么修改过。当时的 block layer 是针对 HDD 设计的。我们都知道,HDD 的随机 I/O 性能其实很差,每秒钟也就几百的吞吐量,延迟也要达到毫秒级。I/O 性能的瓶颈在于硬件,而不在内核 —— 论文说,当时的内核 block layer 吞吐可以达到百万 IOPS ,用于应对 HDD,绰绰有余。Block layer 的设计也比较简单,采用一个全局共享的请求队列(Request Queue):
图片来自论文
Request Queue 全局共享,由一个锁进行保护。所有对 Request Queue 的操作,如加入/移除一个 I/O 请求,I/O 何必,I/O 重排序,I/O 调度等,都需要进行互斥。
在现代高并发、低延迟的硬件环境下,Request Queue 成为了 block layer 的主要瓶颈。 另外,文章还提到另外两个问题:
猜测一下 block layer 设计成全局一个请求队列的原因:
和 HDD 相比,SSD 的随机性能有了质的提升:
除此之外,多核 CPU (包括 NUMA)的发展,也会影响到 block layer 的设计。新 block layer 的设计,要解决的就两个问题:
原来的全局请求队列主要有两个功能:
新的设计将这两个功能拆开,用两级队列来分别完成这两个功能:
图片来自论文
对上层开发的影响,主要在 block layer 对 I/O 的优化有一些改变——不会发生跨队列的 I/O 优化。Block layer 对 I/O 的优化主要有两种:
[1] Linux Block IO: Introducing Multi-queue SSD Access on Multi-core Systems
[2] The multiqueue block layer
[3] A block layer introduction part 1: the bio layer
[4] Block layer introduction part 2: the request layer
[5] The Linux Block Layer - Built for Fast Storage
[6] Blk-mq Is Almost Feature Complete & Fast With Linux 3.16
[7] Linux kernel 5.0+ switching to Multi-Queue Block as default