diff --git a/benchmark/fs/writefile-promises.js b/benchmark/fs/writefile-promises.js new file mode 100644 index 00000000000000..2ba25184ff3132 --- /dev/null +++ b/benchmark/fs/writefile-promises.js @@ -0,0 +1,76 @@ +// Call fs.promises.writeFile over and over again really fast. +// Then see how many times it got called. +// Yes, this is a silly benchmark. Most benchmarks are silly. +'use strict'; + +const path = require('path'); +const common = require('../common.js'); +const fs = require('fs'); +const assert = require('assert'); +const tmpdir = require('../../test/common/tmpdir'); + +tmpdir.refresh(); +const filename = path.resolve(tmpdir.path, + `.removeme-benchmark-garbage-${process.pid}`); +let filesWritten = 0; +const bench = common.createBenchmark(main, { + duration: [5], + encodingType: ['buf', 'asc', 'utf'], + size: [2, 1024, 65535, 1024 * 1024], + concurrent: [1, 10] +}); + +function main({ encodingType, duration, concurrent, size }) { + let encoding; + let chunk; + switch (encodingType) { + case 'buf': + chunk = Buffer.alloc(size, 'b'); + break; + case 'asc': + chunk = 'a'.repeat(size); + encoding = 'ascii'; + break; + case 'utf': + chunk = 'ΓΌ'.repeat(Math.ceil(size / 2)); + encoding = 'utf8'; + break; + default: + throw new Error(`invalid encodingType: ${encodingType}`); + } + + let writes = 0; + let benchEnded = false; + bench.start(); + setTimeout(() => { + benchEnded = true; + bench.end(writes); + for (let i = 0; i < filesWritten; i++) { + try { fs.unlinkSync(`${filename}-${i}`); } catch { } + } + process.exit(0); + }, duration * 1000); + + function write() { + fs.promises.writeFile(`${filename}-${filesWritten++}`, chunk, encoding) + .then(() => afterWrite()) + .catch((err) => afterWrite(err)); + } + + function afterWrite(er) { + if (er) { + if (er.code === 'ENOENT') { + // Only OK if unlinked by the timer from main. + assert.ok(benchEnded); + return; + } + throw er; + } + + writes++; + if (!benchEnded) + write(); + } + + while (concurrent--) write(); +} diff --git a/lib/internal/fs/promises.js b/lib/internal/fs/promises.js index aa927a3dff575d..125e27545cb567 100644 --- a/lib/internal/fs/promises.js +++ b/lib/internal/fs/promises.js @@ -6,7 +6,7 @@ const kIoMaxLength = 2 ** 31 - 1; const kReadFileBufferLength = 512 * 1024; const kReadFileUnknownBufferLength = 64 * 1024; -const kWriteFileMaxChunkSize = 2 ** 14; +const kWriteFileMaxChunkSize = 512 * 1024; const { ArrayPrototypePush, diff --git a/test/parallel/test-fs-promises-file-handle-writeFile.js b/test/parallel/test-fs-promises-file-handle-writeFile.js index bd90a79149b5f1..7ad1beb4bcdd7b 100644 --- a/test/parallel/test-fs-promises-file-handle-writeFile.js +++ b/test/parallel/test-fs-promises-file-handle-writeFile.js @@ -30,7 +30,7 @@ async function validateWriteFile() { async function doWriteAndCancel() { const filePathForHandle = path.resolve(tmpDir, 'dogs-running.txt'); const fileHandle = await open(filePathForHandle, 'w+'); - const buffer = Buffer.from('dogs running'.repeat(10000), 'utf8'); + const buffer = Buffer.from('dogs running'.repeat(512 * 1024), 'utf8'); const controller = new AbortController(); const { signal } = controller; process.nextTick(() => controller.abort());