开发者
内核态AIO VS 用户态AIO

内核态AIO VS 用户态AIO

内核操作系统性能调优IO

发表于 2026/04/30

0

作者|黎炳材

背景介绍

在当今高并发、IO 密集型的系统架构中,异步 IO(AIO)一直是提升性能的关键技术。然而,关于“AIO 应该放在哪里实现”的讨论,业界存在着明显的分水岭:内核态 AIO 与 用户态 AIO。内核态 AIO 依托于操作系统提供的原生接口(如 Linux 的 io_uring 或传统的 libaio),理论上能减少系统调用开销,实现真正的异步语义;而用户态 AIO 则通过在应用层模拟异步行为(如基于事件循环 + 线程池),虽然绕过了内核调度的某些局限,但可能引入额外的内存复制和上下文切换。理解这两者的本质区别,是构建高性能存储系统或网络服务的基石。

用户态AIO

普遍使用的是POSIX AIO。是一个用户级实现,在多个线程中执行正常的阻塞 I/O,从而给人一种 I/O 异步的错觉。这样做的主要原因是:

1.它适用于任何文件系统

2.它基本上可以在任何操作系统上运行(记住GNU的LIBC是便携的)

3.它适用于启用缓冲(即未设置O_DIRECT标志)的文件

主要缺点是队列深度(即实际可完成的未完成操作数量)受限于你选择的线程数,这也意味着一个磁盘上的慢操作可能会阻碍到另一个磁盘的操作。这也会影响内核和磁盘调度器能看到的输入/操作系统(或数量)。

内核态AIO

普遍使用的是LIBAIO,是内核对异步I/O操作的支持,其中IO请求实际上被排队在内核中,按你所用的磁盘调度器排序,其中部分请求会以理想顺序转发到实际磁盘,作为异步操作(使用TCQ或NCQ)。

模拟测试

接下来我们采用NVME硬盘、测试工具FIO可进行实测模拟。分别采用不同的队列深度和线程数对POSIX AIO和LIBAIO进行测试,结果如预期一致,用户态 POSIX AIO性能与线程数强相关。这说明了业务如果使用了用户态AIO,需要特别关注他的IO线程数量。

IO模式

队列深度

线程数

性能比例

测试命令

LIBAIO



1



20



100%



fio -name=rand_read

      -filename=/dev/nvme8n1 -iodepth=1 -ioengine=libaio -direct=1 -bs=128k

      -size=10g -numjobs=20 -rw=randread -runtime=20 -group_reporting

      --time_based  



LIBAIO



20



1



100%


fio -name=rand_read

      -filename=/dev/nvme8n1 -iodepth=20 -ioengine=libaio -direct=1 -bs=128k

      -size=10g -numjobs=1 -rw=randread -runtime=20 -group_reporting --time_based



POSIXAIO



1



20



100%

fio -name=rand_read

      -filename=/dev/nvme8n1 -iodepth=1 -ioengine=posixaio -direct=1 -bs=128k

      -size=10g -numjobs=20 -rw=randread -runtime=20 -group_reporting

      --time_based  



POSIXAIO



20



1



45%

fio -name=rand_read

      -filename=/dev/nvme8n1 -iodepth=20 -ioengine=posixaio -direct=1 -bs=128k

      -size=10g -numjobs=1 -rw=randread -runtime=20 -group_reporting --time_based



开源软件trafficserver业务测试

问题背景:业务性能未达到硬盘性能瓶颈,怀疑业务配置有误。

最后在官方文档中查找到了相关资料,发现该软件默认使用的是线程AIO即用户态AIO。业务性能与AIO数量强相关,通过扩大IO线程数量后性能提升36%