From b0e34edb44526d7cf949086773b99ff3807f23be Mon Sep 17 00:00:00 2001 From: Ilyas Shabi Date: Mon, 9 Oct 2023 15:30:19 +0200 Subject: [PATCH] fs: improve error performance of readvSync --- benchmark/fs/bench-readvSync.js | 58 +++++++++++++++++++++++++++++++++ lib/fs.js | 6 +--- src/node_file.cc | 14 ++++---- 3 files changed, 67 insertions(+), 11 deletions(-) create mode 100644 benchmark/fs/bench-readvSync.js diff --git a/benchmark/fs/bench-readvSync.js b/benchmark/fs/bench-readvSync.js new file mode 100644 index 00000000000000..c163429b5f6212 --- /dev/null +++ b/benchmark/fs/bench-readvSync.js @@ -0,0 +1,58 @@ +'use strict'; + +const common = require('../common'); +const fs = require('fs'); +const assert = require('assert'); +const tmpdir = require('../../test/common/tmpdir'); +tmpdir.refresh(); + +const exptectedBuff = Buffer.from('Benchmark Data'); +const expectedLength = exptectedBuff.length; + +const bufferArr = [Buffer.alloc(expectedLength)]; + +const filename = tmpdir.resolve('readv_sync.txt'); +fs.writeFileSync(filename, exptectedBuff); + +const bench = common.createBenchmark(main, { + type: ['valid', 'invalid'], + n: [1e5], +}); + +function main({ n, type }) { + let fd; + let result; + + switch (type) { + case 'valid': + fd = fs.openSync(filename, 'r'); + + bench.start(); + for (let i = 0; i < n; i++) { + result = fs.readvSync(fd, bufferArr, 0); + } + + bench.end(n); + assert.strictEqual(result, expectedLength); + fs.closeSync(fd); + break; + case 'invalid': { + fd = 1 << 30; + let hasError = false; + bench.start(); + for (let i = 0; i < n; i++) { + try { + result = fs.readvSync(fd, bufferArr, 0); + } catch { + hasError = true; + } + } + + bench.end(n); + assert(hasError); + break; + } + default: + throw new Error('Invalid type'); + } +} diff --git a/lib/fs.js b/lib/fs.js index 037bbed9af66a1..a55930f90b4dab 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -805,14 +805,10 @@ function readvSync(fd, buffers, position) { fd = getValidatedFd(fd); validateBufferArray(buffers); - const ctx = {}; - if (typeof position !== 'number') position = null; - const result = binding.readBuffers(fd, buffers, position, undefined, ctx); - handleErrorFromBinding(ctx); - return result; + return binding.readBuffers(fd, buffers, position); } /** diff --git a/src/node_file.cc b/src/node_file.cc index 20b91bb9b6e439..8f0b5917e46871 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -2483,18 +2483,20 @@ static void ReadBuffers(const FunctionCallbackInfo& args) { iovs[i] = uv_buf_init(Buffer::Data(buffer), Buffer::Length(buffer)); } - FSReqBase* req_wrap_async = GetReqWrap(args, 3); - if (req_wrap_async != nullptr) { // readBuffers(fd, buffers, pos, req) + if (argc > 3) { // readBuffers(fd, buffers, pos, req) + FSReqBase* req_wrap_async = GetReqWrap(args, 3); FS_ASYNC_TRACE_BEGIN0(UV_FS_READ, req_wrap_async) AsyncCall(env, req_wrap_async, args, "read", UTF8, AfterInteger, uv_fs_read, fd, *iovs, iovs.length(), pos); } else { // readBuffers(fd, buffers, undefined, ctx) - CHECK_EQ(argc, 5); - FSReqWrapSync req_wrap_sync; + FSReqWrapSync req_wrap_sync("read"); FS_SYNC_TRACE_BEGIN(read); - int bytesRead = SyncCall(env, /* ctx */ args[4], &req_wrap_sync, "read", - uv_fs_read, fd, *iovs, iovs.length(), pos); + int bytesRead = SyncCallAndThrowOnError( + env, &req_wrap_sync, uv_fs_read, fd, *iovs, iovs.length(), pos); FS_SYNC_TRACE_END(read, "bytesRead", bytesRead); + if (is_uv_error(bytesRead)) { + return; + } args.GetReturnValue().Set(bytesRead); } }