为什么缓冲 I/O 比无缓冲 I/O 快

Why is buffered I/O faster than unbuffered I/O

在阅读 this 时,我找到了一个合理的答案,上面写着:

Case 1: Directly Writing to File On Disk

100 times x 1 ms = 100 ms

我明白了。接下来,

Case 3: Buffering in Memory before Writing to File on Disk

(100 times x 0.5 ms) + 1 ms = 51 ms

1毫秒没看懂。向磁盘写入 100 个数据和向磁盘写入 1 个数据有什么区别?为什么两者都花费 1 毫秒?

这是因为光盘的物理工作原理。 他们可以使用更大的缓冲区(称为页面)并一次性保存它们。 如果你想一直保存数据,你需要对一页进行多次更改,如果你使用缓冲区,你可以编辑快速访问的内存,然后一次性保存所有内容。

他的例子是在解释运营成本。 为了将内存加载到数据,您需要 0.5 秒的成本进行 100 次操作,然后您需要更改磁盘(IO 操作)之一,答案中没有描述并且可能并不明显,几乎所有磁盘都提供批量传输更改操作。所以1个IO操作意味着1次保存到光盘,不一定是1位保存(它可以是更多数据)。

磁盘访问(将数据传输到磁盘)不会逐字节发生,它发生在中。所以,我们不能得出结论,如果写入1字节数据所花费的时间是1毫秒,那么x字节数据将花费x 女士。不是线性关系。

一次写入磁盘的数据量取决于块大小。例如,如果磁盘访问花费您 1 毫秒,并且块大小为 512 字节,那么写入 1 到 512 字节之间的大小将花费您相同的时间,仅 1 毫秒。

所以,回到方程式,如果你有 ,比如 20 次迭代的每个操作要写入 16 个字节的数据,那么,

  • 直写案例

时间 = (20 迭代 * 1 毫秒) == 20 毫秒.

  • 用于缓冲访问

time = (20 iteration * 0.5 ms (bufferring time)) + 1 ms (一次写入) = 10 + 1 == 11 女士

除其他事项外,数据仅 "blocks" 整体写入磁盘。一个块通常为 512 字节。即使您只更改块内的单个字节,OS 和磁盘也必须写入所有 512 个字节。如果在写入前更改块中的所有 512 个字节,实际写入不会比仅更改一个字节慢。

OS and/or 磁盘内部的自动缓存实际上在很大程度上避免了这个问题。但是,每个 "real" 写操作都需要从您的程序调用 OS 并且可能一直到磁盘驱动程序。这需要一些时间。相比之下,将 char/byte/... 数组写入您自己进程内存中的 RAM 中几乎不需要任何成本。

一次写入1个字节时,每次写入需要:

  1. 磁盘寻道时间(可能会有所不同)以将 'head' 置于 磁盘上的正确轨道,
  2. 等待磁盘的正确扇区位于 'head' 下方时的磁盘旋转延迟时间。
  3. 读取扇区时的磁盘读取时间,(旋转延迟 和扇区读取时间可能必须执行不止一次,如果 CRC 与磁盘上保存的不匹配
  4. 将新字节插入扇区中的正确位置
  5. 等待正确扇区再次位于 'head'
  6. 下的旋转延迟
  7. 扇区写入时间(包括新的 CRC)。

为每个字节重复上述所有操作(尤其是因为磁盘比内存慢几个数量级)需要很多时间。

写入整个数据扇区所需的时间不比更新单个字节的时间长。
这就是为什么写入一个充满数据的缓冲区比写入一系列单独的字节要快得多的原因。

还有其他开销,例如更新 inode:

  • 跟踪目录
  • 跟踪单个文件

每次更新文件时,每个目录和文件 inode 都会更新。

那些索引节点(简单地)是磁盘上的其他扇区。总体而言,每次修改文件时都会占用大量磁盘 activity。

因此,只修改文件一次而不是多次修改可以节省大量时间。缓冲是用于最小化磁盘活动数量的技术。