优化O_DIRECT写入

时间:2011-07-25 10:50:21

标签: c++ c linux io

我正在尝试编写一个需要非常快速地写入磁盘的应用程序。我已经达到了写入磁盘的性能目标,这很棒。

但是,我注意到写入磁盘这么快就占用了大量的CPU时间:一个核心最大化,另一个核心占80%,另外两个核心占10-20%。所以我听说O_DIRECT可以通过避免所有这些副本进入内核空间然后复制到磁盘来降低CPU消耗。

我运行了一个小测试程序,证实了这一点 - CPU使用率下降到一个核心的50% - 好多了。

然而,我从来没有像进行正常写入时那样获得完全相同的吞吐量并快速完成,我不得不使用真正的大记录大小(类似于130MB!)

所以,问题是,我想:

  • 对于写入,是否有比O_DIRECT更好的方法来降低CPU使用率? 或
  • 如何获得与内核相似的吞吐量?

我的环境是Linux,我使用的是RAID 50,我能够缓冲写入,直到达到最佳记录大小。一次只会有一位作家。

3 个答案:

答案 0 :(得分:2)

引用this page

  

使用O_DIRECT,内核将直接从/作为[a]参数传递给读/写系统调用的用户空间缓冲区指向的物理内存执行DMA。因此,在用户空间内存和内核缓存之间的副本中不会占用CPU和内存带宽,并且在内核中不会花费CPU时间来管理缓存(如缓存查找,每页锁等)。

使用O_DIRECT时,基本上您正在交换CPU性能的吞吐量。内核停止为您优化吞吐量,作为回报,您可以获得可预测的结果和完全控制。

长话短说:使用O_DIRECT,你必须进行缓存和其他自我优化,从而提高吞吐量。巨大的记录大小现在看起来并不那么奇怪。

我不知道任何其他方法,但我不是Linux大师。随意问一下:)

答案 1 :(得分:0)

您是否尝试过使用mmapmsync?我不知道它是否更快或更少CPU密集,但因为它代表了I / O的另一种方法(基本上它是为你做I / O的内核),它可能是一个有趣的场所。

答案 2 :(得分:0)

您需要以某种方式安排更多的I / O同时保存在飞行中并以最佳尺寸提交。当内核将写入I / O缓冲在一起时,可能会产生许多好处:

  • 可以将连续的I / O合并为更大的I / O.如果是这样的话,就有机会节省开销,因为而不是在内核中提交8个小的4KBytes I / O,现在可以提交1个64Kbyte的I / O(例如)。
  • 它开启了并行提交的可能性。如果内核能够批量处理256k,它现在可以将其作为8个同步I / O发送,从而实现更高的iodepth。

所以

  

对于写入,有没有比O_DIRECT更好的方法来降低CPU使用率?

是将更大的I / O发送到磁盘所需的最佳大小。

  

如何获得与内核相似的吞吐量?

理想情况下执行以上操作(发送最佳大小的I / O)并确保磁盘所需的最大I / O一次保持在飞行中(例如,通过异步提交或通过多个线程/进程提交,如果您要使用阻塞例程)并以磁盘的LBA顺序提交I / O.一个稍微不那么理想的技巧是发送大量I / O并强制内核拆分它们以创建并行性但这不太理想。