Linux ublk 引入批量 IO 调度:性能再突破
大家好,今天咱们来聊聊 Linux 内核存储栈的一个新动向。Linux 的用户态块设备驱动框架(ublk)正在引入“批量 I/O 调度”(Batch I/O Dispatch)机制,这波操作直接让性能数据又上了一个台阶。
如果你关注高性能存储,或者在折腾 SPDK、云原生存储这类东西,这个更新绝对值得留意。
ublk 是个啥?
在说新功能之前,咱们先简单回顾一下 ublk。
以前咱们要在用户态搞个块设备(比如给虚拟机挂个盘,或者搞个自研的分布式存储客户端),通常会用 NBD 或者 loop 设备,但那性能懂的都懂,光是内核态和用户态之间的上下文切换就能把 CPU 吃满,延迟还高。
后来 Ming Lei 大佬搞出了 ublk(Userspace Block Device Driver),并在 Linux 6.0 进了主线。它最大的特点就是基于 io_uring。通过 io_uring 的环形缓冲区和零拷贝特性,用户态程序能极其高效地和内核交换 I/O 请求。简单说,就是让用户态写块设备驱动像在内核态一样快,甚至在某些场景下,因为策略灵活,跑得比内核默认路径还要好。
这次更新了什么?
这次的新补丁集,核心功能叫 UBLK_F_BATCH_IO。
在此之前,ublk 虽然已经很快了,但处理 I/O 还是比较“老实”的——基本上是一个请求对应一个通知。虽然 io_uring 本身支持批量提交,但在 ublk 的具体调度路径上,还有优化的空间。
新的“批量 I/O 调度”机制改变了这一点:
- 1. 按队列操作:命令现在是基于队列(Queue)而不是单个 I/O 来操作的。
- 2. 批量处理:多个 I/O 可以在一次操作中被处理。
- 3. 减少通知开销:这是最关键的。通过允许在一个
uring_cmd 中完成多个 I/O,大幅减少了内核通知用户态“活儿干完了”的次数。
简单理解就是:以前是送一个快递打一次电话,现在是攒一车快递打一个电话,效率自然就上来了。
性能提升了多少?
基于这组补丁的测试数据相当亮眼。测试场景包含 16 个并发任务:
- • 涉及页面拷贝(Page Copies)的场景:性能提升了 12%。
- • 零拷贝(Zero-Copy)场景:性能提升了约 3.7%。
即便是单任务(Single Job)这种很难通过并发掩盖延迟的场景,也能看到提升:
对于这种已经压榨得很极致的底层驱动来说,双位数的提升是非常可观的。
技术细节与未来
这组补丁不仅仅是提速,还带来了一些架构上的灵活性:
- • 灵活的任务分配:任何任务都可以处理任何 I/O,不再需要绑定特定的 I/O 守护进程。
而且,作者 Ming Lei 在补丁说明里还提到,这为未来的优化铺平了道路,比如支持 io-poll(轮询模式,进一步降低延迟)、释放 blk-mq 的批量标签(batch tags)等。
什么时候能用上?
目前这部分代码已经进入了 Jens Axboe 的 for-next 分支。按照内核的开发节奏,如果不出意外,它将在 2 月份的合并窗口期间合并。
不管版本号是叫 6.20 还是直接跳到 7.1,反正咱们离用上这个特性不远了。
总结
Linux 存储栈正变得越来越“用户态化”。ublk 结合 io_uring 正在蚕食原本属于 SPDK 的领地,同时又保持了作为通用内核驱动的兼容性。对于开发者来说,这意味着以后写高性能存储应用门槛更低了,不用非得去啃内核源码,在用户态也能跑出接近硬件极限的性能。
咱们拭目以待这个补丁正式合入主线。
信息来源:
- • https://lore.kernel.org/all/20260116141859.719929-1-ming.lei@redhat.com/