mirror of
https://github.com/nodejs/node.git
synced 2025-05-05 15:32:15 +00:00

This increases the maximum buffer size per read to 512kb when using `fs.readFile`. This is important to improve the read performance for bigger files. PR-URL: https://github.com/nodejs/node/pull/27063 Refs: https://github.com/nodejs/node/issues/25741 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Jamie Davis <davisjam@vt.edu>
118 lines
2.9 KiB
JavaScript
118 lines
2.9 KiB
JavaScript
'use strict';
|
|
|
|
const { Math } = primordials;
|
|
|
|
const { Buffer } = require('buffer');
|
|
|
|
const { FSReqCallback, close, read } = internalBinding('fs');
|
|
|
|
// Use 64kb in case the file type is not a regular file and thus do not know the
|
|
// actual file size. Increasing the value further results in more frequent over
|
|
// allocation for small files and consumes CPU time and memory that should be
|
|
// used else wise.
|
|
// Use up to 512kb per read otherwise to partition reading big files to prevent
|
|
// blocking other threads in case the available threads are all in use.
|
|
const kReadFileUnknownBufferLength = 64 * 1024;
|
|
const kReadFileBufferLength = 512 * 1024;
|
|
|
|
function readFileAfterRead(err, bytesRead) {
|
|
const context = this.context;
|
|
|
|
if (err)
|
|
return context.close(err);
|
|
|
|
context.pos += bytesRead;
|
|
|
|
if (context.pos === context.size || bytesRead === 0) {
|
|
context.close();
|
|
} else {
|
|
if (context.size === 0) {
|
|
// Unknown size, just read until we don't get bytes.
|
|
const buffer = bytesRead === kReadFileUnknownBufferLength ?
|
|
context.buffer : context.buffer.slice(0, bytesRead);
|
|
context.buffers.push(buffer);
|
|
}
|
|
context.read();
|
|
}
|
|
}
|
|
|
|
function readFileAfterClose(err) {
|
|
const context = this.context;
|
|
const callback = context.callback;
|
|
let buffer = null;
|
|
|
|
if (context.err || err)
|
|
return callback(context.err || err);
|
|
|
|
try {
|
|
if (context.size === 0)
|
|
buffer = Buffer.concat(context.buffers, context.pos);
|
|
else if (context.pos < context.size)
|
|
buffer = context.buffer.slice(0, context.pos);
|
|
else
|
|
buffer = context.buffer;
|
|
|
|
if (context.encoding)
|
|
buffer = buffer.toString(context.encoding);
|
|
} catch (err) {
|
|
return callback(err);
|
|
}
|
|
|
|
callback(null, buffer);
|
|
}
|
|
|
|
class ReadFileContext {
|
|
constructor(callback, encoding) {
|
|
this.fd = undefined;
|
|
this.isUserFd = undefined;
|
|
this.size = 0;
|
|
this.callback = callback;
|
|
this.buffers = null;
|
|
this.buffer = null;
|
|
this.pos = 0;
|
|
this.encoding = encoding;
|
|
this.err = null;
|
|
}
|
|
|
|
read() {
|
|
let buffer;
|
|
let offset;
|
|
let length;
|
|
|
|
if (this.size === 0) {
|
|
buffer = Buffer.allocUnsafeSlow(kReadFileUnknownBufferLength);
|
|
offset = 0;
|
|
length = kReadFileUnknownBufferLength;
|
|
this.buffer = buffer;
|
|
} else {
|
|
buffer = this.buffer;
|
|
offset = this.pos;
|
|
length = Math.min(kReadFileBufferLength, this.size - this.pos);
|
|
}
|
|
|
|
const req = new FSReqCallback();
|
|
req.oncomplete = readFileAfterRead;
|
|
req.context = this;
|
|
|
|
read(this.fd, buffer, offset, length, -1, req);
|
|
}
|
|
|
|
close(err) {
|
|
const req = new FSReqCallback();
|
|
req.oncomplete = readFileAfterClose;
|
|
req.context = this;
|
|
this.err = err;
|
|
|
|
if (this.isUserFd) {
|
|
process.nextTick(function tick() {
|
|
req.oncomplete(null);
|
|
});
|
|
return;
|
|
}
|
|
|
|
close(this.fd, req);
|
|
}
|
|
}
|
|
|
|
module.exports = ReadFileContext;
|