19

我正在编写一个 C 程序,通过直接从原始块设备文件读取数据来从 SSD 驱动器读取数据。

我正在尝试Linux AIO(我说的是Linux AIO API,即由linuxaio.h诸如io_submit(...)等提供的功能,而不是POSIX AIO API)。我使用标志打开块设备文件,O_DIRECT并确保写入缓冲区与块大小对齐。

我注意到 Linux AIO 它比使用带有O_DIRECT标志的同步 IO 快得多。

最让我惊讶的是,通过使用 Linux AIO 发出许多几 KB 的小随机读取所获得的吞吐量明显高于使用同步 I/O 和O_DIRECT.

所以,我想知道:为什么 Linux AIO 的性能比同步 I/O 更好?使用 AIO 时内核做了什么?内核是否执行请求重新排序?与使用同步 I/O 相比,使用 Linux AIO 会导致更高的 CPU 利用率吗?

非常感谢提前

4

1 回答 1

28

简短回答: AIO 实现很可能“更快”,因为它并行提交多个 IO,而同步实现有零个或一个 I/O 在运行。它与写入内存或内核 I/O 路径对同步 I/O 有额外开销无关。

您可以使用iostat -x -d 1进行检查。查看avgqu-sz(平均队列大小 = 正在运行的 I/O 的平均数量)和%util(利用率 = 设备向其发出至少一个 I/O 的时间百分比)。

长答案:

  • 在谈论 I/O 时,“更快”的概念很棘手。“更快”是否意味着更高的带宽?还是更低的延迟?还是给定请求大小的带宽?还是给定队列深度的延迟?还是延迟、带宽、请求大小、队列深度和许多其他参数或工作负载的组合?我在这里假设您正在考虑吞吐量/带宽,但是,请记住,存储设备的性能不是单一维度的指标。

  • SSD 是高度并行的设备。SSD由许多闪存芯片组成,每个芯片都有多个可以独立读取/写入的裸片。SSD 利用这一点并并行执行许多 I/O,而响应时间没有明显增加。因此,就吞吐量而言,SSD 看到多少并发 I/O 非常重要。

  • 让我们了解当线程提交同步 I/O 时会发生什么:a) 线程花费一些 CPU 周期来准备 I/O 请求(生成数据、计算偏移量、将数据复制到缓冲区等),b) 系统调用是执行(例如,pread()),执行传递到内核空间,线程阻塞,c)内核处理 I/O 请求并遍历各个内核 I/O 层,d)提交 I/O 请求到设备并遍历互连(例如 PCIe),e) I/O 请求由 SSD 固件处理,f) 实际读取命令发送到相应的闪存芯片,g) SSD 控制器等待数据, h) SSD 控制器从闪存芯片获取数据并通过互连发送。此时,数据离开 SSD,阶段 ea) 反向发生。

  • 如您所见,同步 I/O 进程正在与 SSD 进行请求乒乓球比赛。在上述许多阶段中,实际上没有从闪存芯片中读取数据。最重要的是,尽管您的 SSD 可以并行处理数十到数百个请求,但它在任何给定时刻最多只能看到一个请求。因此,吞吐量非常非常低,因为您实际上并没有真正使用 SSD。

  • 异步 I/O 有两种帮助:a) 它允许进程并行提交多个 I/O 请求(SSD 有足够的工作来保持忙碌),b) 它允许通过各个处理阶段流水线化 I/O(因此将阶段延迟与吞吐量解耦)。

  • 您看到异步 I/O 比同步 I/O 更快的原因是因为您比较了苹果和橘子。同步吞吐量是在给定的请求大小、低队列深度且没有流水线的情况下。异步吞吐量具有不同的请求大小、更高的队列深度和流水线。你看到的数字没有可比性。

  • 大多数 I/O 密集型应用程序(即大多数应用程序,如数据库、Web 服务器等)都有许多执行同步 I/O 的线程。尽管每个线程在任何给定时刻最多可以提交一个 I/O,但内核和 SSD 设备会看到许多可以并行处理的 I/O 请求。多个同步 I/O 请求与多个异步 I/O 请求具有相同的好处。

    异步和同步 I/O 的主要区别在于 I/O 和进程的调度方式以及编程模型。如果操作正确,异步和同步 I/O 都可以从存储设备中压缩相同的 IOPS/吞吐量。

于 2015-03-12T13:23:56.630 回答