我正在编写一个C程序,通过直接从原始块设备文件中读取SSD驱动器中的数据。
我正在尝试Linux AIO(我说的是Linux AIO API,即linuxaio.h
提供的功能,例如io_submit(...)
等,而不是POSIX AIO API。我使用O_DIRECT
标志打开块设备文件,并确保写入缓冲区与块大小对齐。
我注意到Linux AIO比使用O_DIRECT
标志的同步IO要快得多。
最让我感到惊讶的是,通过使用Linux AIO发出许多小的随机读取数,每个使用Linux AIO实现的吞吐量显着高于使用同步I /进行几个MB的大(顺序)读取所实现的吞吐量O和O_DIRECT
。
所以,我想知道:为什么Linux AIO比同步I / O更好?使用AIO时内核会做什么?内核是否执行请求重新排序?与使用同步I / O相比,使用Linux AIO会导致更高的CPU利用率吗?
提前多多感谢
答案 0 :(得分:25)
简答: 很可能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并且阶段e-a)反向发生。
如您所见,同步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的方式。处理调度和编程模型。 async和amp;如果操作正确,同步I / O可以从存储设备中挤出相同的IOPS /吞吐量。