From 593d4ba3f47fbebad30934f5a8e9607673cd69df Mon Sep 17 00:00:00 2001 From: pluris Date: Wed, 4 Oct 2023 11:27:02 +0900 Subject: [PATCH] fs:improve error performance for `readSync` --- benchmark/fs/bench-readSync.js | 57 +++++++++++++++++++++++++++++++++ lib/fs.js | 6 +--- src/node_file.cc | 15 +++++---- typings/internalBinding/fs.d.ts | 1 + 4 files changed, 67 insertions(+), 12 deletions(-) create mode 100644 benchmark/fs/bench-readSync.js diff --git a/benchmark/fs/bench-readSync.js b/benchmark/fs/bench-readSync.js new file mode 100644 index 00000000000000..57c8c9165da6f3 --- /dev/null +++ b/benchmark/fs/bench-readSync.js @@ -0,0 +1,57 @@ +'use strict'; + +const common = require('../common'); +const fs = require('fs'); +const tmpdir = require('../../test/common/tmpdir'); +tmpdir.refresh(); + +const tmpfile = tmpdir.resolve(`.existing-file-${process.pid}`); +fs.writeFileSync(tmpfile, 'this-is-for-a-benchmark', 'utf8'); + +const bench = common.createBenchmark(main, { + type: ['existing', 'non-existing'], + paramType: ['offset-and-length', 'no-offset-and-length'], + n: [1e4], +}); + +function main({ n, type, paramType }) { + let fd; + + switch (type) { + case 'existing': + fd = fs.openSync(tmpfile, 'r', 0o666); + break; + case 'non-existing': + fd = 1 << 30; + break; + default: + new Error('Invalid type'); + } + + bench.start(); + switch (paramType) { + case 'offset-and-length': + for (let i = 0; i < n; i++) { + try { + fs.readSync(fd, Buffer.alloc(1), 0, 1, 0); + } catch { + // Continue regardless of error. + } + } + break; + case 'no-offset-and-length': + for (let i = 0; i < n; i++) { + try { + fs.readSync(fd, Buffer.alloc(1)); + } catch { + // Continue regardless of error. + } + } + break; + default: + new Error('Invalid type'); + } + bench.end(n); + + if (fd === 'existing') fs.closeSync(fd); +} diff --git a/lib/fs.js b/lib/fs.js index 585458fddd6c1f..6a229f851518e2 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -751,11 +751,7 @@ function readSync(fd, buffer, offsetOrOptions, length, position) { validatePosition(position, 'position', length); } - const ctx = {}; - const result = binding.read(fd, buffer, offset, length, position, - undefined, ctx); - handleErrorFromBinding(ctx); - return result; + return binding.read(fd, buffer, offset, length, position); } /** diff --git a/src/node_file.cc b/src/node_file.cc index 778e9139e4dc93..807af0bcbb6c2a 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -2364,17 +2364,18 @@ static void Read(const FunctionCallbackInfo& args) { char* buf = buffer_data + off; uv_buf_t uvbuf = uv_buf_init(buf, len); - FSReqBase* req_wrap_async = GetReqWrap(args, 5); - if (req_wrap_async != nullptr) { // read(fd, buffer, offset, len, pos, req) + if (argc > 5) { // read(fd, buffer, offset, len, pos, req) + FSReqBase* req_wrap_async = GetReqWrap(args, 5); + CHECK_NOT_NULL(req_wrap_async); FS_ASYNC_TRACE_BEGIN0(UV_FS_READ, req_wrap_async) AsyncCall(env, req_wrap_async, args, "read", UTF8, AfterInteger, uv_fs_read, fd, &uvbuf, 1, pos); - } else { // read(fd, buffer, offset, len, pos, undefined, ctx) - CHECK_EQ(argc, 7); - FSReqWrapSync req_wrap_sync; + } else { // read(fd, buffer, offset, len, pos) + FSReqWrapSync req_wrap_sync("read"); FS_SYNC_TRACE_BEGIN(read); - const int bytesRead = SyncCall(env, args[6], &req_wrap_sync, "read", - uv_fs_read, fd, &uvbuf, 1, pos); + const int bytesRead = SyncCallAndThrowOnError(env, &req_wrap_sync, + uv_fs_read, fd, &uvbuf, 1, + pos); FS_SYNC_TRACE_END(read, "bytesRead", bytesRead); args.GetReturnValue().Set(bytesRead); } diff --git a/typings/internalBinding/fs.d.ts b/typings/internalBinding/fs.d.ts index b4c4cd6e79a91c..957f106adaa4c7 100644 --- a/typings/internalBinding/fs.d.ts +++ b/typings/internalBinding/fs.d.ts @@ -157,6 +157,7 @@ declare namespace InternalFSBinding { function read(fd: number, buffer: ArrayBufferView, offset: number, length: number, position: number, req: FSReqCallback): void; function read(fd: number, buffer: ArrayBufferView, offset: number, length: number, position: number, req: undefined, ctx: FSSyncContext): number; function read(fd: number, buffer: ArrayBufferView, offset: number, length: number, position: number, usePromises: typeof kUsePromises): Promise; + function read(fd: number, buffer: ArrayBufferView, offset: number, length: number, position: number): number; function readBuffers(fd: number, buffers: ArrayBufferView[], position: number, req: FSReqCallback): void; function readBuffers(fd: number, buffers: ArrayBufferView[], position: number, req: undefined, ctx: FSSyncContext): number;