From 27b2ce5ba633f28c7220e5614f689bae3e48ce23 Mon Sep 17 00:00:00 2001 From: IlyasShabi <33763729+IlyasShabi@users.noreply.github.com> Date: Tue, 5 Dec 2023 19:31:23 +0100 Subject: [PATCH] fs: improve error performance of readvSync PR-URL: https://github.com/nodejs/node/pull/50100 Refs: https://github.com/nodejs/performance/issues/106 Reviewed-By: Yagiz Nizipli Reviewed-By: Antoine du Hamel --- 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 f52f9e8f48d3b9..c26979a65e0664 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -801,14 +801,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 0855bda583a62d..e426319daf7856 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -2467,18 +2467,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); } }