Skip to content

Commit 9b7260d

Browse files
committed
fs: improve error performance for rmdirSync
1 parent 740ca54 commit 9b7260d

File tree

4 files changed

+95
-16
lines changed

4 files changed

+95
-16
lines changed

benchmark/fs/bench-rmdirSync.js

+44
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
const fs = require('fs');
5+
const path = require('path');
6+
const tmpdir = require('../../test/common/tmpdir');
7+
tmpdir.refresh();
8+
9+
const bench = common.createBenchmark(main, {
10+
type: ['existing', 'non-existing'],
11+
n: [1e3],
12+
});
13+
14+
function main({ n, type }) {
15+
let files;
16+
17+
switch (type) {
18+
case 'existing':
19+
files = [];
20+
21+
// Populate tmpdir with mock dirs
22+
for (let i = 0; i < n; i++) {
23+
const path = tmpdir.resolve(`rmdirsync-bench-dir-${i}`);
24+
fs.mkdirSync(path);
25+
files.push(path);
26+
}
27+
break;
28+
case 'non-existing':
29+
files = new Array(n).fill(tmpdir.resolve(`.non-existing-file-${Date.now()}`));
30+
break;
31+
default:
32+
new Error('Invalid type');
33+
}
34+
35+
bench.start();
36+
for (let i = 0; i < n; i++) {
37+
try {
38+
fs.rmdirSync(files[i]);
39+
} catch {
40+
// do nothing
41+
}
42+
}
43+
bench.end(n);
44+
}

lib/fs.js

+1-16
Original file line numberDiff line numberDiff line change
@@ -1194,22 +1194,7 @@ function rmdir(path, options, callback) {
11941194
* @returns {void}
11951195
*/
11961196
function rmdirSync(path, options) {
1197-
path = getValidatedPath(path);
1198-
1199-
if (options?.recursive) {
1200-
emitRecursiveRmdirWarning();
1201-
options = validateRmOptionsSync(path, { ...options, force: false }, true);
1202-
if (options !== false) {
1203-
lazyLoadRimraf();
1204-
return rimrafSync(pathModule.toNamespacedPath(path), options);
1205-
}
1206-
} else {
1207-
validateRmdirOptions(options);
1208-
}
1209-
1210-
const ctx = { path };
1211-
binding.rmdir(pathModule.toNamespacedPath(path), undefined, ctx);
1212-
return handleErrorFromBinding(ctx);
1197+
return syncFs.rmdirSync(path, options);
12131198
}
12141199

12151200
/**

lib/internal/fs/sync.js

+27
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,24 @@
22

33
const pathModule = require('path');
44
const {
5+
emitRecursiveRmdirWarning,
56
getValidatedPath,
67
stringToFlags,
78
getValidMode,
89
getStatsFromBinding,
910
getStatFsFromBinding,
1011
getValidatedFd,
12+
validateRmOptionsSync,
13+
validateRmdirOptions,
1114
} = require('internal/fs/utils');
1215
const { parseFileMode } = require('internal/validators');
1316

17+
let rimrafSync;
18+
function lazyLoadRimraf() {
19+
if (rimraf === undefined)
20+
({ rimrafSync } = require('internal/fs/rimraf'));
21+
}
22+
1423
const binding = internalBinding('fs');
1524

1625
/**
@@ -86,6 +95,23 @@ function close(fd) {
8695
return binding.closeSync(fd);
8796
}
8897

98+
function rmdirSync(path, options) {
99+
path = getValidatedPath(path);
100+
101+
if (options?.recursive) {
102+
emitRecursiveRmdirWarning();
103+
options = validateRmOptionsSync(path, { ...options, force: false }, true);
104+
if (options !== false) {
105+
lazyLoadRimraf();
106+
return rimrafSync(pathModule.toNamespacedPath(path), options);
107+
}
108+
} else {
109+
validateRmdirOptions(options);
110+
}
111+
112+
return binding.rmdirSync(pathModule.toNamespacedPath(path));
113+
}
114+
89115
module.exports = {
90116
readFileUtf8,
91117
exists,
@@ -95,4 +121,5 @@ module.exports = {
95121
statfs,
96122
open,
97123
close,
124+
rmdirSync
98125
};

src/node_file.cc

+23
Original file line numberDiff line numberDiff line change
@@ -1694,6 +1694,27 @@ static void RMDir(const FunctionCallbackInfo<Value>& args) {
16941694
}
16951695
}
16961696

1697+
static void RMDirSync(const FunctionCallbackInfo<Value>& args) {
1698+
Environment* env = Environment::GetCurrent(args);
1699+
1700+
const int argc = args.Length();
1701+
CHECK_GE(argc, 1);
1702+
1703+
BufferValue path(env->isolate(), args[0]);
1704+
CHECK_NOT_NULL(*path);
1705+
THROW_IF_INSUFFICIENT_PERMISSIONS(
1706+
env, permission::PermissionScope::kFileSystemWrite, path.ToStringView());
1707+
1708+
uv_fs_t req;
1709+
auto make = OnScopeLeave([&req]() { uv_fs_req_cleanup(&req); });
1710+
FS_SYNC_TRACE_BEGIN(rmdir);
1711+
int err = uv_fs_rmdir(nullptr, &req, *path, nullptr);
1712+
FS_SYNC_TRACE_END(rmdir);
1713+
if (err < 0) {
1714+
return env->ThrowUVException(err, "rmdir", nullptr, *path);
1715+
}
1716+
}
1717+
16971718
int MKDirpSync(uv_loop_t* loop,
16981719
uv_fs_t* req,
16991720
const std::string& path,
@@ -3365,6 +3386,7 @@ static void CreatePerIsolateProperties(IsolateData* isolate_data,
33653386
SetMethod(isolate, target, "rename", Rename);
33663387
SetMethod(isolate, target, "ftruncate", FTruncate);
33673388
SetMethod(isolate, target, "rmdir", RMDir);
3389+
SetMethodNoSideEffect(isolate, target, "rmdirSync", RMDirSync);
33683390
SetMethod(isolate, target, "mkdir", MKDir);
33693391
SetMethod(isolate, target, "readdir", ReadDir);
33703392
SetMethod(isolate, target, "internalModuleReadJSON", InternalModuleReadJSON);
@@ -3490,6 +3512,7 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
34903512
registry->Register(Rename);
34913513
registry->Register(FTruncate);
34923514
registry->Register(RMDir);
3515+
registry->Register(RMDirSync);
34933516
registry->Register(MKDir);
34943517
registry->Register(ReadDir);
34953518
registry->Register(InternalModuleReadJSON);

0 commit comments

Comments
 (0)