Skip to content

Commit afd0b68

Browse files
committed
fs: improve fsPromises readFile performance
Improve the fsPromises readFile performance by allocating only one buffer, when size is known, increase the size of the readbuffer chunks, and dont read more data if size bytes have been read refs: #37583 Backport-PR-URL: #37608
1 parent 8899f47 commit afd0b68

File tree

1 file changed

+36
-14
lines changed

1 file changed

+36
-14
lines changed

lib/internal/fs/promises.js

+36-14
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@
44
// See https://github.com/libuv/libuv/pull/1501.
55
const kIoMaxLength = 2 ** 31 - 1;
66

7-
// Note: This is different from kReadFileBufferLength used for non-promisified
8-
// fs.readFile.
9-
const kReadFileMaxChunkSize = 2 ** 14;
7+
const kReadFileBufferLength = 512 * 1024;
8+
const kReadFileUnknownBufferLength = 64 * 1024;
109
const kWriteFileMaxChunkSize = 2 ** 14;
1110

1211
const {
12+
ArrayPrototypePush,
1313
Error,
1414
MathMax,
1515
MathMin,
@@ -272,21 +272,43 @@ async function readFileHandle(filehandle, options) {
272272
if (size > kIoMaxLength)
273273
throw new ERR_FS_FILE_TOO_LARGE(size);
274274

275-
const chunks = [];
276-
const chunkSize = size === 0 ?
277-
kReadFileMaxChunkSize :
278-
MathMin(size, kReadFileMaxChunkSize);
279275
let endOfFile = false;
276+
let totalRead = 0;
277+
const noSize = size === 0;
278+
const buffers = [];
279+
const fullBuffer = noSize ? undefined : Buffer.allocUnsafeSlow(size);
280280
do {
281-
const buf = Buffer.alloc(chunkSize);
282-
const { bytesRead, buffer } =
283-
await read(filehandle, buf, 0, chunkSize, -1);
284-
endOfFile = bytesRead === 0;
285-
if (bytesRead > 0)
286-
chunks.push(buffer.slice(0, bytesRead));
281+
let buffer;
282+
let offset;
283+
let length;
284+
if (noSize) {
285+
buffer = Buffer.allocUnsafeSlow(kReadFileUnknownBufferLength);
286+
offset = 0;
287+
length = kReadFileUnknownBufferLength;
288+
} else {
289+
buffer = fullBuffer;
290+
offset = totalRead;
291+
length = MathMin(size - totalRead, kReadFileBufferLength);
292+
}
293+
294+
const bytesRead = (await binding.read(filehandle.fd, buffer, offset,
295+
length, -1, kUsePromises)) || 0;
296+
totalRead += bytesRead;
297+
endOfFile = bytesRead === 0 || totalRead === size;
298+
if (noSize && bytesRead > 0) {
299+
const isBufferFull = bytesRead === kReadFileUnknownBufferLength;
300+
const chunkBuffer = isBufferFull ? buffer : buffer.slice(0, bytesRead);
301+
ArrayPrototypePush(buffers, chunkBuffer);
302+
}
287303
} while (!endOfFile);
288304

289-
const result = Buffer.concat(chunks);
305+
let result;
306+
if (size > 0) {
307+
result = totalRead === size ? fullBuffer : fullBuffer.slice(0, totalRead);
308+
} else {
309+
result = buffers.length === 1 ? buffers[0] : Buffer.concat(buffers,
310+
totalRead);
311+
}
290312

291313
return options.encoding ? result.toString(options.encoding) : result;
292314
}

0 commit comments

Comments
 (0)