本文翻译自 How to read files quickly in JavaScript,作者:Daniel Lemire, 略有删改。

假设你需要在服务器上使用JavaScript读取多个文件。在像Node.js这样的运行时环境中,JavaScript有多种读取文件的方式。哪一种是最好的呢?让我们来看看各种方法的测试结果。

使用fs. promise

const fs = require('fs/promises');
const readFile = fs.readFile;
readFile("lipsum.txt", { encoding: 'utf-8' })
  .then((data) => {...})
  .catch((err) => {...})

使用fs.readFile和util.promisify

const fs = require('fs');
const util = require('util');
const readFile = util.promisify(fs.readFile);
readFile("lipsum.txt", { encoding: 'utf-8' })  
  .then((data) => {...})
  .catch((err) => {...})

使用fs.readFileSync

const fs = require('fs');
const readFileSync = fs.readFileSync;
var data = readFileSync("lipsum.txt", { encoding: 'utf-8' })

使用await fs.readFileSync

const fs = require('fs');
const readFileSync = fs.readFileSync;
async function f(name, options) {
  return readFileSync(name, options);
}

使用fs.readFile

const fs = require('fs');
const readFile = fs.readFile;
fs.readFile('lipsum.txt', function read(err, data) {...});

测试

我写了一个小型基准测试,用于反复从磁盘读取文件。这是一个简单的循环,每次都会访问相同的文件。我记录了读取文件5万次所需的毫秒数。这个文件相对较小(略超过1千字节)。我使用的是一台拥有数十个Ice Lake Intel核心和大量内存的大型服务器。我使用的Node.js版本是20.1,Bun版本是1.0.14

我多次运行了基准测试,并且在所有情况下都记录了最好的结果。你的结果可能会有所不同。

时间(Node.js)时间(Bun)
fs.promises2400 ms110 ms
fs.readFile和util.promisify1500 ms180 ms
fs.readFileSync140 ms140 ms
await fs.readFileSync220 ms180 ms
fs.readFile760 ms90 ms

至少在我的系统上,在这个测试中使用Node.js时,fs.promises比其他方式都要慢的多。在这个测试中Bun比Node.js快得多。

从某种意义上来说,fs.promises 的结果比看上去更差。我发现 readFileSync 使用了 300 毫秒的 CPU 时间,而 fs.promises 却使用了 7 秒的 CPU 时间。这是因为在进行基准测试时,fs.promises 在多个核心上触发了工作。

即使将文件大小增加到32kB,结论也并没有改变。如果你使用更大的文件,许多Node.js案例会因为“堆内存分配失败”而失败。但Bun即使处理大文件也能继续运行。测试结果并没有改变关于Bun的结论:在我的测试中,fs.readFile始终更快,即使对于大文件也是如此。


看完本文如果觉得有用,记得点个赞支持,收藏起来说不定哪天就用上啦~

专注前端开发,分享前端相关技术干货,公众号:南城大前端(ID: nanchengfe)


南城FE
2.2k 声望574 粉丝