From 246d1534aadc05a8309cd703041048eab6a5fefe Mon Sep 17 00:00:00 2001 From: Yagiz Nizipli Date: Fri, 29 Sep 2023 13:08:40 -0400 Subject: [PATCH] fs: improve error performance of `renameSync` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/49962 Refs: https://github.com/nodejs/performance/issues/106 Reviewed-By: Matteo Collina Reviewed-By: Stephen Belanger Reviewed-By: Vinícius Lourenço Claro Cardoso --- benchmark/fs/bench-renameSync.js | 49 ++++++++++++++++++++++++++++++++ lib/fs.js | 8 +++--- src/node_file.cc | 15 +++++----- typings/internalBinding/fs.d.ts | 1 + 4 files changed, 61 insertions(+), 12 deletions(-) create mode 100644 benchmark/fs/bench-renameSync.js diff --git a/benchmark/fs/bench-renameSync.js b/benchmark/fs/bench-renameSync.js new file mode 100644 index 00000000000000..9f9f5e4e84cda0 --- /dev/null +++ b/benchmark/fs/bench-renameSync.js @@ -0,0 +1,49 @@ +'use strict'; + +const common = require('../common'); +const fs = require('fs'); +const assert = require('assert'); +const tmpdir = require('../../test/common/tmpdir'); + +const bench = common.createBenchmark(main, { + type: ['invalid', 'valid'], + n: [2e3], +}); + +function main({ n, type }) { + switch (type) { + case 'invalid': { + let hasError = false; + bench.start(); + for (let i = 0; i < n; i++) { + try { + fs.renameSync(tmpdir.resolve(`.non-existing-file-${i}`), tmpdir.resolve(`.new-file-${i}`)); + } catch { + hasError = true; + } + } + bench.end(n); + assert(hasError); + break; + } + case 'valid': { + tmpdir.refresh(); + for (let i = 0; i < n; i++) { + fs.writeFileSync(tmpdir.resolve(`.existing-file-${i}`), 'bench', 'utf8'); + } + + bench.start(); + for (let i = 0; i < n; i++) { + fs.renameSync( + tmpdir.resolve(`.existing-file-${i}`), + tmpdir.resolve(`.new-existing-file-${i}`), + ); + } + + bench.end(n); + break; + } + default: + throw new Error('Invalid type'); + } +} diff --git a/lib/fs.js b/lib/fs.js index 2d5170cd2f44b0..ae1b831775d707 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -1034,10 +1034,10 @@ function rename(oldPath, newPath, callback) { function renameSync(oldPath, newPath) { oldPath = getValidatedPath(oldPath, 'oldPath'); newPath = getValidatedPath(newPath, 'newPath'); - const ctx = { path: oldPath, dest: newPath }; - binding.rename(pathModule.toNamespacedPath(oldPath), - pathModule.toNamespacedPath(newPath), undefined, ctx); - handleErrorFromBinding(ctx); + binding.rename( + pathModule.toNamespacedPath(oldPath), + pathModule.toNamespacedPath(newPath), + ); } /** diff --git a/src/node_file.cc b/src/node_file.cc index afaa028784e710..1c24f1614b46f2 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -1432,7 +1432,7 @@ static void Rename(const FunctionCallbackInfo& args) { Isolate* isolate = env->isolate(); const int argc = args.Length(); - CHECK_GE(argc, 3); + CHECK_GE(argc, 2); BufferValue old_path(isolate, args[0]); CHECK_NOT_NULL(*old_path); @@ -1449,8 +1449,8 @@ static void Rename(const FunctionCallbackInfo& args) { permission::PermissionScope::kFileSystemWrite, new_path.ToStringView()); - FSReqBase* req_wrap_async = GetReqWrap(args, 2); - if (req_wrap_async != nullptr) { + if (argc > 2) { // rename(old_path, new_path, req) + FSReqBase* req_wrap_async = GetReqWrap(args, 2); FS_ASYNC_TRACE_BEGIN2(UV_FS_RENAME, req_wrap_async, "old_path", @@ -1460,12 +1460,11 @@ static void Rename(const FunctionCallbackInfo& args) { AsyncDestCall(env, req_wrap_async, args, "rename", *new_path, new_path.length(), UTF8, AfterNoArgs, uv_fs_rename, *old_path, *new_path); - } else { - CHECK_EQ(argc, 4); - FSReqWrapSync req_wrap_sync; + } else { // rename(old_path, new_path) + FSReqWrapSync req_wrap_sync("rename", *old_path, *new_path); FS_SYNC_TRACE_BEGIN(rename); - SyncCall(env, args[3], &req_wrap_sync, "rename", uv_fs_rename, - *old_path, *new_path); + SyncCallAndThrowOnError( + env, &req_wrap_sync, uv_fs_rename, *old_path, *new_path); FS_SYNC_TRACE_END(rename); } } diff --git a/typings/internalBinding/fs.d.ts b/typings/internalBinding/fs.d.ts index c4dd973293ab22..bdab2e80be7f26 100644 --- a/typings/internalBinding/fs.d.ts +++ b/typings/internalBinding/fs.d.ts @@ -183,6 +183,7 @@ declare namespace InternalFSBinding { function rename(oldPath: string, newPath: string, req: FSReqCallback): void; function rename(oldPath: string, newPath: string, req: undefined, ctx: FSSyncContext): void; function rename(oldPath: string, newPath: string, usePromises: typeof kUsePromises): Promise; + function rename(oldPath: string, newPath: string): void; function rmdir(path: string, req: FSReqCallback): void; function rmdir(path: string, req: undefined, ctx: FSSyncContext): void;