为什么带有'直接'(O_DIRECT)标志的dd如此快得多?

Jos*_*vin 10 c linux io file dd

我有一台服务器,RAID50配置为24个驱动器(两组12个),如果我运行:

dd if=/dev/zero of=ddfile2 bs=1M count=1953 oflag=direct
Run Code Online (Sandbox Code Playgroud)

我明白了:

2047868928 bytes (2.0 GB) copied, 0.805075 s, 2.5 GB/s
Run Code Online (Sandbox Code Playgroud)

但如果我跑:

dd if=/dev/zero of=ddfile2 bs=1M count=1953
Run Code Online (Sandbox Code Playgroud)

我明白了:

2047868928 bytes (2.0 GB) copied, 2.53489 s, 808 MB/s
Run Code Online (Sandbox Code Playgroud)

我知道O_DIRECT会导致页面缓存被绕过.但据我所知,它绕过页面缓存基本上意味着避免使用memcpy.使用带宽工具在我的桌面上进行测试我的最差情况是顺序内存写入带宽为14GB/s,我想在更新的更昂贵的服务器上,带宽必须更好.那么为什么额外的memcpy会导致> 2x减速?使用页面缓存时是否真的涉及更多内容?这不典型吗?

Ano*_*non 14

在这种oflag=direct情况下:

  • 您正在为内核提供直接写入数据的能力,而不是等待缓冲区达到阈值/超时而导致同步被强制(这意味着它不太可能被阻止在同步之后不相关的数据).
  • 在某些情况下,弄脏缓冲区比刷新它们的速度更快将导致程序生成脏缓冲区,直到释放任意限制的压力为止(请参阅SUSE的"具有大RAM的SLES 11/12服务器上的低写入性能") .
  • 您正在保存内核工作(没有额外的副本从userland到内核,不需要执行大多数缓冲区缓存管理操作).

更一般地说,巨大的块大小(1MByte)可能比RAID的块大小更大,因此I/O将在内核中分离,并且那些较小的块并行提交,因此您可以通过微小的I /来从缓冲的回写中获得合并Os不值得.

鉴于上述所有情况,如果您在原始缓冲副本期间最大化单个CPU(但磁盘可以处理更多吞吐量),那么执行md0复制应该更快,因为可用于用户空间/服务磁盘I/O的CPU时间更多内核开销的减少.

那么为什么额外的memcpy会导致> 2x减速?

这不仅仅涉及每个I/O的额外memcpy - 考虑必须维护的所有额外缓存机制.

使用页面缓存时是否真的涉及更多内容?

是! 关于如何将缓冲区复制到内核不是即时的,以及在回应Linux async(io_submit)写入v/s正常(缓冲)写入问题时页面压力如何减慢速度,这是一个很好的解释.但是,除非您的程序能够足够快地生成数据并且CPU过载,否则它无法足够快地提供磁盘,因此通常不会显示或重要.

这不典型吗?

不,您使用的工作量非常典型.我想如果块大小很小(例如512),那将是一个不同的结果.

简介:您的I/O模式并没有真正受益于缓冲(I/O非常庞大,数据没有被重用,I/O是流顺序的),因此您/sys/block/md0/queue/optimal_io_size处于更快的最佳方案中.请参阅Linux的原始作者O_DIRECT(包含大多数幻灯片的嵌入版本的较长PDF文档)的这些幻灯片,了解其背后的原始动机.