io_uring 背景
AIO现状
系统调用比较多,比较难用
不够异步,没有解决所有的阻塞点,例如内核中的 Block 层的 request 就可能导致阻塞
仅支持 Direct IO(应该是指 unbuffered IO,文件 IO)
IO 请求元数据开销较大,如果请求只有几百字节,浪费很大
IOPOLL 支持不好(即轮询的方式)
现在硬件起来了,软件成为瓶颈
io_uring 优势
简单强大的系统调用,提高三个系统调用,liburing 用户动态库编程友好(
io_uring_setup
,io_uring_enter
, io_uring_register
)通用型强:提供内核同一的异步编程框架,既支持传统 IO (buffer IO + direct IO),也支持 epoll 型编程
特性丰富:支持非常多的高级特性,可想象的空间丰富
高性能:IO 请求 overhead 小
aio - io_uring - spdk 性能对比
io_uring 基本和 spdk 几百持平
io_uring 架构机器重要特性
io_uring 整体架构
两 ring 一线程(ring 即环形队列)
两组 ring buffer,一组用于存放
sqe
,一组用于存放 cqe
,其中 sqe
描述 io 请求,cqe
描述 io 完成(这两个 ring,是通过 mmap
实现用户态和内核态共享的)io_uring_enter(2)
即可以完成提交 io 请求,也可以 reap
完成的 io 请求io_uring 重要特性
IORING_SETUP_SQPOLL
:创建一个内核线程进行 sqe 的处理(io提交),几乎完全清除用户态内核上下文切换,并真正将 IO 裸机 offload,实现业务逻辑与 IO 逻辑的分离
IORING_SETUP_IOPOLL
:配合 blk-mq 多类型硬件队列映射机制,利用此特性,内核 IO 协议栈开始真正完全支持 iopoll
IORING_REGISTER_FILES
&&IORING_REGISTER_BUFFERS
:减少引用计数原子操作的开销,见 https://lwn.net/Articles/787473
IORING_FEAT_FAST_POLL
:网络编程新利器,向 epoll 等传统基于事件驱动的网络编程模型发起挑战,向用户态提供真正的异步编程 API
io_uring 优化工作
汇合 io_uring 到 Anoglis OS 8 内核,并在使用过程中进行相对应的优化,相关优化都已贡献到上游社区。截止目前累计贡献约 60 个补丁。涵盖:
- 特性支持和重构:如扩展 sqpoll,实现 sqpoll percpu 功能
- 性能优化:利用自研 perf-test-for-io_uring 测试套件优化多个性能瓶颈
- Bug Fix:利用 Abaci Fuzz Platform 发现并解决大量竞争、死锁等 BUG
io_uring 应用实践
图数据库引擎
业务特点:
- Direct IO
- 4KB Size
- 容器环境
- 混部场景
优化策略:
- 开启 sqpoll 特性
- 开启 iopoll 特性
- 使用 register files 特性
- 更高精度的 sqthread 工作/睡眠机制
- 业务上下文参与提交 IO
- 提高 sqthread 的优先级
- 优化容器 CPU 资源统计
Netty
Netty 目前已支持 io_uring,利用 io_uring 的 IORING_FEAT_FAST_POLL 特性: