性能测试
看到一篇英文博客《How to read files quickly in JavaScript》对 JS 常用的 5 中文件读取方法做一个性能测试:
测试方案:同一个文件(大约 1KB),读 50000 次,看耗时情况。
测试环境:一台几十个 Intel 核心和充足内存的服务器。
语言环境:Node 20.1 和 Bun 1.0.14
-
test1.js (
fs/promises
)const fs = require("fs/promises"); const readFile = fs.readFile; let start = Date.now(); let count = 0; const N = 50000; for (let i = 0; i < N; i++) { readFile("lipsum.txt", { encoding: "utf-8" }) .then((data) => { if (data.length != 1335) throw 1; count++; if (count == N) { end = Date.now(); console.log("time: ", end - start); } }) .catch((err) => { throw 1; }); }
-
test2.js (
fs.readFile
+util.promisify
)const fs = require("fs"); const util = require("util"); const readFile = util.promisify(fs.readFile); let start = Date.now(); let count = 0; const N = 50000; for (let i = 0; i < N; i++) { readFile("lipsum.txt", { encoding: "utf-8" }) .then((data) => { if (data.length != 1335) throw 1; count++; if (count == N) { end = Date.now(); console.log("time: ", end - start); } }) .catch((err) => { throw 1; }); }
-
test3.js (
fs.readFileSync
)const fs = require("fs"); const readFileSync = fs.readFileSync; let start = Date.now(); let count = 0; const N = 50000; for (let i = 0; i < N; i++) { var data = readFileSync("lipsum.txt", { encoding: "utf-8" }); if (data.length != 1335) throw 1; } console.log("time: ", Date.now() - start);
-
test4.js (
fs.readFileSync
+promise
)const fs = require("fs"); const readFileSync = fs.readFileSync; async function f(name, options) { return readFileSync(name, options); } let start = Date.now(); let count = 0; const N = 50000; for (let i = 0; i < N; i++) { f("lipsum.txt", { encoding: "utf-8" }) .then((data) => { if (data.length != 1335) throw 1; count++; if (count == N) { end = Date.now(); console.log("time: ", end - start); } }) .catch((err) => { throw 1; }); }
-
test5.js (
fs.readFile
)const fs = require("fs"); const readFile = fs.readFile; let start = Date.now(); let count = 0; const N = 50000; for (let i = 0; i < N; i++) { fs.readFile("lipsum.txt", function read(err, data) { if (err) { throw 1; } if (data.length != 1335) throw 1; count++; if (count == N) { end = Date.now(); console.log("time: ", end - start); start = end; } }); }
-
测试脚本
for i in {1..10}; do echo "trial ${i}" echo "node" node --version node test1.js > /dev/null node test1.js node test2.js > /dev/null node test2.js node test3.js > /dev/null node test3.js node test4.js > /dev/null node test4.js node test5.js > /dev/null node test5.js echo "Bun" bun run test1.js > /dev/null bun run test1.js bun run test2.js > /dev/null bun run test2.js bun run test3.js > /dev/null bun run test3.js bun run test4.js > /dev/null bun run test4.js bun run test5.js > /dev/null bun run test5.js done
PS:以上代码在 GitHub 上可以找到。
测试结果
Time (Node) | Time (Bun) | |
---|---|---|
fs/promises | 2400 ms | 110 ms |
fs.readFile & util.promisify | 1500 ms | 180 ms |
fs.readFileSync | 140 ms | 140 ms |
await fs.readFileSync | 220 ms | 180 ms |
fs.readFile | 760 ms | 90 ms |
说明:
- Node 的 promise 不行(Bun 好得多)
- 文件增大到 32KB 测试,Node 会报 heap limit Allocation failed(堆限制分配失败)
Bun 没有问题,但是结论还是不受影响。