Skip to content

Commit 6ec5aba

Browse files
CanadaHonktargos
authored andcommitted
fs: improve error performance for mkdirSync
PR-URL: #49847 Refs: nodejs/performance#106 Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
1 parent 465ad2a commit 6ec5aba

4 files changed

Lines changed: 68 additions & 40 deletions

File tree

‎benchmark/fs/bench-mkdirSync.js‎

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
'use strict';
2+
3+
constcommon=require('../common');
4+
constfs=require('fs');
5+
consttmpdir=require('../../test/common/tmpdir');
6+
tmpdir.refresh();
7+
8+
constbench=common.createBenchmark(main,{
9+
type: ['existing','non-existing'],
10+
recursive: ['true','false'],
11+
n: [1e3],
12+
});
13+
14+
functionmain({ n, type, recursive }){
15+
recursive=recursive==='true';
16+
letfiles;
17+
18+
switch(type){
19+
case'non-existing':
20+
files=[];
21+
22+
// Populate tmpdir with target dirs
23+
for(leti=0;i<n;i++){
24+
constpath=tmpdir.resolve(recursive ? `rmdirsync-bench-dir-${process.pid}-${i}/a/b/c` : `rmdirsync-bench-dir-${process.pid}-${i}`);
25+
files.push(path);
26+
}
27+
break;
28+
case'existing':
29+
files=newArray(n).fill(__dirname);
30+
break;
31+
default:
32+
newError('Invalid type');
33+
}
34+
35+
bench.start();
36+
for(leti=0;i<n;i++){
37+
try{
38+
fs.mkdirSync(files[i],{ recursive });
39+
}catch{
40+
// do nothing
41+
}
42+
}
43+
bench.end(n);
44+
}

‎lib/fs.js‎

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1385,11 +1385,12 @@ function mkdirSync(path, options) {
13851385
path=getValidatedPath(path);
13861386
validateBoolean(recursive,'options.recursive');
13871387

1388-
constctx={ path };
1389-
constresult=binding.mkdir(pathModule.toNamespacedPath(path),
1390-
parseFileMode(mode,'mode'),recursive,
1391-
undefined,ctx);
1392-
handleErrorFromBinding(ctx);
1388+
constresult=binding.mkdir(
1389+
pathModule.toNamespacedPath(path),
1390+
parseFileMode(mode,'mode'),
1391+
recursive,
1392+
);
1393+
13931394
if(recursive){
13941395
returnresult;
13951396
}

‎src/node_file.cc‎

Lines changed: 15 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1751,30 +1751,11 @@ int MKDirpAsync(uv_loop_t* loop,
17511751
return err;
17521752
}
17531753

1754-
intCallMKDirpSync(Environment* env, const FunctionCallbackInfo<Value>& args,
1755-
FSReqWrapSync* req_wrap, constchar* path, int mode) {
1756-
env->PrintSyncTrace();
1757-
int err = MKDirpSync(env->event_loop(), &req_wrap->req, path, mode,
1758-
nullptr);
1759-
if (err < 0) {
1760-
v8::Local<v8::Context> context = env->context();
1761-
v8::Local<v8::Object> ctx_obj = args[4].As<v8::Object>();
1762-
v8::Isolate* isolate = env->isolate();
1763-
ctx_obj->Set(context,
1764-
env->errno_string(),
1765-
v8::Integer::New(isolate, err)).Check();
1766-
ctx_obj->Set(context,
1767-
env->syscall_string(),
1768-
OneByteString(isolate, "mkdir")).Check();
1769-
}
1770-
return err;
1771-
}
1772-
17731754
staticvoidMKDir(const FunctionCallbackInfo<Value>& args) {
17741755
Environment* env = Environment::GetCurrent(args);
17751756

17761757
constint argc = args.Length();
1777-
CHECK_GE(argc, 4);
1758+
CHECK_GE(argc, 3);
17781759

17791760
BufferValue path(env->isolate(), args[0]);
17801761
CHECK_NOT_NULL(*path);
@@ -1787,37 +1768,39 @@ static void MKDir(const FunctionCallbackInfo<Value>& args) {
17871768
CHECK(args[2]->IsBoolean());
17881769
bool mkdirp = args[2]->IsTrue();
17891770

1790-
FSReqBase* req_wrap_async = GetReqWrap(args, 3);
1791-
if (req_wrap_async != nullptr) { // mkdir(path, mode, req)
1771+
if (argc > 3) { // mkdir(path, mode, recursive, req)
1772+
FSReqBase* req_wrap_async = GetReqWrap(args, 3);
17921773
FS_ASYNC_TRACE_BEGIN1(
17931774
UV_FS_UNLINK, req_wrap_async, "path", TRACE_STR_COPY(*path))
17941775
AsyncCall(env, req_wrap_async, args, "mkdir", UTF8,
17951776
mkdirp ? AfterMkdirp : AfterNoArgs,
17961777
mkdirp ? MKDirpAsync : uv_fs_mkdir, *path, mode);
1797-
} else { // mkdir(path, mode, undefined, ctx)
1798-
CHECK_EQ(argc, 5);
1799-
FSReqWrapSync req_wrap_sync;
1778+
} else { // mkdir(path, mode, recursive)
1779+
FSReqWrapSync req_wrap_sync("mkdir", *path);
18001780
FS_SYNC_TRACE_BEGIN(mkdir);
18011781
if (mkdirp) {
1802-
int err = CallMKDirpSync(env, args, &req_wrap_sync, *path, mode);
1803-
if (err == 0 &&
1804-
!req_wrap_sync.continuation_data()->first_path().empty()) {
1782+
env->PrintSyncTrace();
1783+
int err = MKDirpSync(
1784+
env->event_loop(), &req_wrap_sync.req, *path, mode, nullptr);
1785+
if (is_uv_error(err)) {
1786+
env->ThrowUVException(err, "mkdir", nullptr, *path);
1787+
return;
1788+
}
1789+
if (!req_wrap_sync.continuation_data()->first_path().empty()) {
18051790
Local<Value> error;
18061791
std::string first_path(req_wrap_sync.continuation_data()->first_path());
18071792
FromNamespacedPath(&first_path);
18081793
MaybeLocal<Value> path = StringBytes::Encode(env->isolate(),
18091794
first_path.c_str(),
18101795
UTF8, &error);
18111796
if (path.IsEmpty()) {
1812-
Local<Object> ctx = args[4].As<Object>();
1813-
ctx->Set(env->context(), env->error_string(), error).Check();
1797+
env->isolate()->ThrowException(error);
18141798
return;
18151799
}
18161800
args.GetReturnValue().Set(path.ToLocalChecked());
18171801
}
18181802
} else {
1819-
SyncCall(env, args[4], &req_wrap_sync, "mkdir",
1820-
uv_fs_mkdir, *path, mode);
1803+
SyncCallAndThrowOnError(env, &req_wrap_sync, uv_fs_mkdir, *path, mode);
18211804
}
18221805
FS_SYNC_TRACE_END(mkdir);
18231806
}

‎typings/internalBinding/fs.d.ts‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -146,9 +146,9 @@ declare namespace InternalFSBinding {
146146
functionmkdir(path: string,mode: number,recursive: boolean,req: FSReqCallback<void|string>): void;
147147
functionmkdir(path: string,mode: number,recursive: true,req: FSReqCallback<string>): void;
148148
functionmkdir(path: string,mode: number,recursive: false,req: FSReqCallback<void>): void;
149-
functionmkdir(path: string,mode: number,recursive: boolean,req: undefined,ctx: FSSyncContext): void|string;
150-
functionmkdir(path: string,mode: number,recursive: true,req: undefined,ctx: FSSyncContext): string;
151-
functionmkdir(path: string,mode: number,recursive: false,req: undefined,ctx: FSSyncContext): void;
149+
functionmkdir(path: string,mode: number,recursive: boolean): void|string;
150+
functionmkdir(path: string,mode: number,recursive: true): string;
151+
functionmkdir(path: string,mode: number,recursive: false): void;
152152
functionmkdir(path: string,mode: number,recursive: boolean,usePromises: typeofkUsePromises): Promise<void|string>;
153153
functionmkdir(path: string,mode: number,recursive: true,usePromises: typeofkUsePromises): Promise<string>;
154154
functionmkdir(path: string,mode: number,recursive: false,usePromises: typeofkUsePromises): Promise<void>;

0 commit comments

Comments
 (0)