From 0d59dda780aa5d4b5824807780b60ffbaf858536 Mon Sep 17 00:00:00 2001 From: CanadaHonk Date: Sun, 26 Nov 2023 19:23:41 +0000 Subject: [PATCH] fs: improve error performance for `rmdirSync` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/nodejs/node/pull/49846 Refs: https://github.com/nodejs/performance/issues/106 Reviewed-By: Yagiz Nizipli Reviewed-By: Joyee Cheung Reviewed-By: Vinícius Lourenço Claro Cardoso --- benchmark/fs/bench-rmdirSync.js | 42 +++++++++++++++++++++++++++++++++ lib/fs.js | 4 +--- src/node_file.cc | 14 +++++------ typings/internalBinding/fs.d.ts | 2 +- 4 files changed, 50 insertions(+), 12 deletions(-) create mode 100644 benchmark/fs/bench-rmdirSync.js diff --git a/benchmark/fs/bench-rmdirSync.js b/benchmark/fs/bench-rmdirSync.js new file mode 100644 index 00000000000000..48103439274371 --- /dev/null +++ b/benchmark/fs/bench-rmdirSync.js @@ -0,0 +1,42 @@ +'use strict'; + +const common = require('../common'); +const fs = require('fs'); +const tmpdir = require('../../test/common/tmpdir'); +tmpdir.refresh(); + +const bench = common.createBenchmark(main, { + type: ['existing', 'non-existing'], + n: [1e4], +}); + +function main({ n, type }) { + switch (type) { + case 'existing': { + for (let i = 0; i < n; i++) { + fs.mkdirSync(tmpdir.resolve(`rmdirsync-bench-dir-${i}`)); + } + + bench.start(); + for (let i = 0; i < n; i++) { + fs.rmdirSync(tmpdir.resolve(`rmdirsync-bench-dir-${i}`)); + } + bench.end(n); + break; + } + case 'non-existing': { + bench.start(); + for (let i = 0; i < n; i++) { + try { + fs.rmdirSync(tmpdir.resolve(`.non-existent-folder-${i}`)); + } catch { + // do nothing + } + } + bench.end(n); + break; + } + default: + new Error('Invalid type'); + } +} diff --git a/lib/fs.js b/lib/fs.js index 5e1165453367f7..d8974e67128fb0 100644 --- a/lib/fs.js +++ b/lib/fs.js @@ -1220,9 +1220,7 @@ function rmdirSync(path, options) { validateRmdirOptions(options); } - const ctx = { path }; - binding.rmdir(pathModule.toNamespacedPath(path), undefined, ctx); - return handleErrorFromBinding(ctx); + binding.rmdir(pathModule.toNamespacedPath(path)); } /** diff --git a/src/node_file.cc b/src/node_file.cc index df0bf442bd58db..b3c52e04fac8f0 100644 --- a/src/node_file.cc +++ b/src/node_file.cc @@ -1588,25 +1588,23 @@ static void RMDir(const FunctionCallbackInfo& args) { Environment* env = Environment::GetCurrent(args); const int argc = args.Length(); - CHECK_GE(argc, 2); + CHECK_GE(argc, 1); BufferValue path(env->isolate(), args[0]); CHECK_NOT_NULL(*path); THROW_IF_INSUFFICIENT_PERMISSIONS( env, permission::PermissionScope::kFileSystemWrite, path.ToStringView()); - FSReqBase* req_wrap_async = GetReqWrap(args, 1); // rmdir(path, req) - if (req_wrap_async != nullptr) { + if (argc > 1) { + FSReqBase* req_wrap_async = GetReqWrap(args, 1); // rmdir(path, req) FS_ASYNC_TRACE_BEGIN1( UV_FS_RMDIR, req_wrap_async, "path", TRACE_STR_COPY(*path)) AsyncCall(env, req_wrap_async, args, "rmdir", UTF8, AfterNoArgs, uv_fs_rmdir, *path); - } else { // rmdir(path, undefined, ctx) - CHECK_EQ(argc, 3); - FSReqWrapSync req_wrap_sync; + } else { // rmdir(path) + FSReqWrapSync req_wrap_sync("rmdir", *path); FS_SYNC_TRACE_BEGIN(rmdir); - SyncCall(env, args[2], &req_wrap_sync, "rmdir", - uv_fs_rmdir, *path); + SyncCallAndThrowOnError(env, &req_wrap_sync, uv_fs_rmdir, *path); FS_SYNC_TRACE_END(rmdir); } } diff --git a/typings/internalBinding/fs.d.ts b/typings/internalBinding/fs.d.ts index 77f20e9550e30a..67c14c73acf7f1 100644 --- a/typings/internalBinding/fs.d.ts +++ b/typings/internalBinding/fs.d.ts @@ -192,7 +192,7 @@ declare namespace InternalFSBinding { function rename(oldPath: string, newPath: string): void; function rmdir(path: string, req: FSReqCallback): void; - function rmdir(path: string, req: undefined, ctx: FSSyncContext): void; + function rmdir(path: string): void; function rmdir(path: string, usePromises: typeof kUsePromises): Promise; function stat(path: StringOrBuffer, useBigint: boolean, req: FSReqCallback): void;