fs.writeFile 是执行顺序 IO 还是随机 IO?

Does fs.writeFile perform sequential or random IO?

提问人:Gabriel Robaina 提问时间:11/4/2023 更新时间:11/4/2023 访问量:51

问:

我正在学习顺序文件IO与随机文件IO,它引起了我的注意,Node文档没有提到函数是顺序IO还是随机IO。与读取文件相关的函数也是如此。fsfs.writeFile

也许它隐含了平台的文件 API 是顺序的。也许抽象会根据文件大小等因素在顺序或随机之间做出决定。我不知道。无论哪种方式,我都是这件事的新手,很想更清楚地了解这个话题。

当一个刚接触 NodeJS 的开发人员从入门页面获取代码时,它到底在做什么?顺序 IO 还是随机 IO?在使用 API 时,我们可以选择其中之一吗?fsfs

const fs = require('fs');
const content = 'Some content!';
fs.writeFile('/Users/joe/test.txt', content, err => {
  if (err) {
    console.error(err);
  }
  // file written successfully
});
node.js 文件-io

评论


答:

1赞 jfriend00 11/4/2023 #1

我假设你问是因为你想知道你是否可以期待顺序写入性能或随机写入性能(随机写入速度要慢得多)。因此,对于这一点,重要的是磁盘控制器级别发生了什么,以及对磁盘其他部分的其他读取/写入是否与读/写交错。

主要是连续的,但这取决于......

如果在内部查看代码,则调用以以下常量定义的最大块大小写入数据:fs.writeFile()writeFileHandle()

const kWriteFileMaxChunkSize = 512 * 1024;

因此,对于 512k 或更小的文件,该文件将通过对操作系统的一次调用来写入,否则,它将被分解为连续的 512k 写入。

现在,至于这是否更接近顺序或随机 IO,这有点复杂。如果操作系统中的任何其他进程在磁盘上没有发生任何其他操作,并且磁盘未进行碎片化,则这些连续的 512k 写入很可能是顺序写入。

但是,如果操作系统在其他进程中对磁盘执行其他操作,则可能需要在多次写入之间移动磁盘头来处理其他进程,这可能更像是随机 IO,因为在每次写入之间都会有磁头搜索磁盘的新部分。但是,由于这些仍然是 512k 写入(不是超小),因此每个 512k 写入仍然有一个顺序 IO 的方面。因此,它可能最终会成为大部分顺序的组合,但偶尔会因为其他磁盘活动交错而随机。writeFileHandle()

如果磁盘碎片严重,那么所有的赌注都会被取消,因为即使是 512k 的写入也可能必须将该写入的不同块放在磁盘的非顺序部分。

评论

0赞 user207421 11/4/2023
从过程的角度来看,它是连续的,这才是最重要的。你太想多了。
0赞 jfriend00 11/4/2023
@user207421 - 在我看来,OP 想知道他们是否可以期望磁盘性能,如顺序写入或随机写入。因此,重要的是在磁盘控制器级别而不是在应用程序级别发生的情况。
0赞 Gabriel Robaina 11/4/2023
感谢您@jfriend00回复。你答对了我的问题。因此,NodeJS 中 fs.write* 代码的目的是使写入尽可能按顺序进行。可能发生的随机 IO 部分是由于来自其他进程或磁盘状态的干扰。您通过分析 fs.write* 底层代码得出了答案。是否有来自 NodeJS 或其他来源的任何参考资料来描述此实现的顺序意图?我找不到。
0赞 jfriend00 11/5/2023
@GabrielRobaina - 没有人会尝试将对单个文件的文件写入到随机操作中,因为这太慢了。随机 IO 的发生可能是由于使用磁盘的其他操作、磁盘碎片或对磁盘执行许多不同操作的代码的干扰 - 而不仅仅是写入一个文件。此外,一次执行大文件写入总是更有可能使您更接近顺序写入性能。
0赞 jfriend00 11/5/2023
@GabrielRobaina - 至于文档,我认为没有。这是一个 API。性能是否更接近顺序性能,更多地与 API 的使用方式有关,而不是 API 的实现方式。它只是按照你的吩咐去做。如果你告诉它向文件写入一个超大的数据块,它将尝试以 512k 块的形式串行写入。如果你告诉它把小块写到文件 A,然后把一个小块写到文件 B,再把一个小块写到文件 C,然后一遍又一遍地重复,你会得到更像随机 IO 的性能。