From 69c87ccc89905fd8111cfa44468144853673d9bb Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Fri, 29 Jan 2021 14:43:08 +0100 Subject: [PATCH 1/3] fs: only use Buffer.concat in promises.readFile when necessary --- lib/internal/fs/promises.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/fs/promises.js b/lib/internal/fs/promises.js index 86e6924ca2104e..951e4ac214a9f2 100644 --- a/lib/internal/fs/promises.js +++ b/lib/internal/fs/promises.js @@ -331,7 +331,7 @@ async function readFileHandle(filehandle, options) { ArrayPrototypePush(chunks, buffer.slice(0, bytesRead)); } while (!endOfFile); - const result = Buffer.concat(chunks); + const result = chunks.length === 1 ? chunks[0] : Buffer.concat(chunks); return options.encoding ? result.toString(options.encoding) : result; } From 5ce769e2381631f23d56b4c01c8065f661695515 Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Fri, 29 Jan 2021 15:14:09 +0100 Subject: [PATCH 2/3] fs: read full size if known in promises.readFile If we have an estimate of the file size available from the previous stat call, use that for the size of the first chunk to be read. This increases performance by reading more data (and, most likely, all data) at once without incurring memory overhead in most situations. --- lib/internal/fs/promises.js | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/lib/internal/fs/promises.js b/lib/internal/fs/promises.js index 951e4ac214a9f2..ef6546030775d1 100644 --- a/lib/internal/fs/promises.js +++ b/lib/internal/fs/promises.js @@ -315,20 +315,21 @@ async function readFileHandle(filehandle, options) { throw new ERR_FS_FILE_TOO_LARGE(size); const chunks = []; - const chunkSize = size === 0 ? - kReadFileMaxChunkSize : - MathMin(size, kReadFileMaxChunkSize); + let isFirstChunk = true; + const firstChunkSize = size === 0 ? kReadFileMaxChunkSize : size; + const chunkSize = Math.min(firstChunkSize, kReadFileMaxChunkSize); let endOfFile = false; do { if (signal?.aborted) { throw lazyDOMException('The operation was aborted', 'AbortError'); } - const buf = Buffer.alloc(chunkSize); + const buf = Buffer.alloc(isFirstChunk ? firstChunkSize : chunkSize); const { bytesRead, buffer } = - await read(filehandle, buf, 0, chunkSize, -1); + await read(filehandle, buf, 0, buf.length, -1); endOfFile = bytesRead === 0; if (bytesRead > 0) ArrayPrototypePush(chunks, buffer.slice(0, bytesRead)); + isFirstChunk = false; } while (!endOfFile); const result = chunks.length === 1 ? chunks[0] : Buffer.concat(chunks); From 759440f2cf61e64780800b7429be03aaf137ab1b Mon Sep 17 00:00:00 2001 From: Anna Henningsen Date: Fri, 29 Jan 2021 15:27:56 +0100 Subject: [PATCH 3/3] fixup! fs: read full size if known in promises.readFile --- lib/internal/fs/promises.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/internal/fs/promises.js b/lib/internal/fs/promises.js index ef6546030775d1..4b568b52b8d106 100644 --- a/lib/internal/fs/promises.js +++ b/lib/internal/fs/promises.js @@ -317,7 +317,7 @@ async function readFileHandle(filehandle, options) { const chunks = []; let isFirstChunk = true; const firstChunkSize = size === 0 ? kReadFileMaxChunkSize : size; - const chunkSize = Math.min(firstChunkSize, kReadFileMaxChunkSize); + const chunkSize = MathMin(firstChunkSize, kReadFileMaxChunkSize); let endOfFile = false; do { if (signal?.aborted) {